From 3ee20531c96c05452a4b832634df000cf5d0dc08 Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Mon, 8 Apr 2019 03:05:03 -0700 Subject: Added Copy/Paste to object properties in Build Tools --- indra/newview/llpanelobject.cpp | 116 ++++++++++++++++++- indra/newview/llpanelobject.h | 24 +++- .../newview/skins/default/textures/icons/Paste.png | Bin 0 -> 530 bytes indra/newview/skins/default/textures/textures.xml | 1 + .../newview/skins/default/xui/en/floater_tools.xml | 126 ++++++++++++++++++--- 5 files changed, 247 insertions(+), 20 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/Paste.png (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 3665910c63..56a19d7551 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -150,6 +150,24 @@ BOOL LLPanelObject::postBuild() mCtrlRotZ = getChild("Rot Z"); childSetCommitCallback("Rot Z",onCommitRotation,this); + // Copy/paste pos + mBtnCopyPos = getChild("copy_pos_btn"); + mBtnCopyPos->setCommitCallback( boost::bind(&LLPanelObject::onCopyPos, this, _2 )); + mBtnPastePos = getChild("paste_pos_btn"); + mBtnPastePos->setCommitCallback( boost::bind(&LLPanelObject::onPastePos, this, _2 )); + + // Copy/paste size + mBtnCopySize = getChild("copy_size_btn"); + mBtnCopySize->setCommitCallback( boost::bind(&LLPanelObject::onCopySize, this, _2 )); + mBtnPasteSize = getChild("paste_size_btn"); + mBtnPasteSize->setCommitCallback( boost::bind(&LLPanelObject::onPasteSize, this, _2 )); + + // Copy/paste rot + mBtnCopyRot = getChild("copy_rot_btn"); + mBtnCopyRot->setCommitCallback( boost::bind(&LLPanelObject::onCopyRot, this, _2 )); + mBtnPasteRot = getChild("paste_rot_btn"); + mBtnPasteRot->setCommitCallback( boost::bind(&LLPanelObject::onPasteRot, this, _2 ));; + //-------------------------------------------------------- // Base Type @@ -286,7 +304,10 @@ LLPanelObject::LLPanelObject() mSelectedType(MI_BOX), mSculptTextureRevert(LLUUID::null), mSculptTypeRevert(0), - mSizeChanged(FALSE) + mSizeChanged(FALSE), + mHasPosClipboard(FALSE), + mHasSizeClipboard(FALSE), + mHasRotClipboard(FALSE) { } @@ -379,6 +400,8 @@ void LLPanelObject::getState( ) mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); mCtrlPosZ->setEnabled(enable_move); + mBtnCopyPos->setEnabled(enable_move); + mBtnPastePos->setEnabled(enable_move && mHasPosClipboard); if (enable_scale) { @@ -404,6 +427,8 @@ void LLPanelObject::getState( ) mCtrlScaleX->setEnabled( enable_scale ); mCtrlScaleY->setEnabled( enable_scale ); mCtrlScaleZ->setEnabled( enable_scale ); + mBtnCopySize->setEnabled( enable_scale ); + mBtnPasteSize->setEnabled( enable_scale && mHasSizeClipboard ); LLQuaternion object_rot = objectp->getRotationEdit(); object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ])); @@ -435,6 +460,8 @@ void LLPanelObject::getState( ) mCtrlRotX->setEnabled( enable_rotate ); mCtrlRotY->setEnabled( enable_rotate ); mCtrlRotZ->setEnabled( enable_rotate ); + mBtnCopyRot->setEnabled( enable_rotate ); + mBtnPasteRot->setEnabled( enable_rotate && mHasRotClipboard ); LLUUID owner_id; std::string owner_name; @@ -2001,3 +2028,90 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } + +void copy_vector_to_clipboard(const LLVector3& vec) +{ + std::string stringVec = llformat("<%g, %g, %g>", vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); +} + +void LLPanelObject::onCopyPos(const LLSD& data) +{ + mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); + + copy_vector_to_clipboard(mClipboardPos); + + mBtnPastePos->setToolTip(llformat("Paste Position\n<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ])); + mBtnPastePos->setEnabled(TRUE); + + mHasPosClipboard = TRUE; +} + +void LLPanelObject::onCopySize(const LLSD& data) +{ + mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); + + copy_vector_to_clipboard(mClipboardSize); + + mBtnPasteSize->setToolTip(llformat("Paste Size\n<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ])); + mBtnPasteSize->setEnabled(TRUE); + + mHasSizeClipboard = TRUE; +} + +void LLPanelObject::onCopyRot(const LLSD& data) +{ + mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); + + copy_vector_to_clipboard(mClipboardRot); + + mBtnPasteRot->setToolTip(llformat("Paste Rotation\n<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ])); + mBtnPasteSize->setEnabled(TRUE); + + mHasRotClipboard = TRUE; +} + +void LLPanelObject::onPastePos(const LLSD& data) +{ + if(!mHasPosClipboard) return; + + // Clamp pos on non-attachments, just keep the prims within the region + if (!mObject->isAttachment()) + { + mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, 256.f); + mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, 256.f); + //height will get properly clammed by sendPosition + } + + mCtrlPosX->set( mClipboardPos.mV[VX] ); + mCtrlPosY->set( mClipboardPos.mV[VY] ); + mCtrlPosZ->set( mClipboardPos.mV[VZ] ); + + sendPosition(FALSE); +} + +void LLPanelObject::onPasteSize(const LLSD& data) +{ + if(!mHasSizeClipboard) return; + + mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + + mCtrlScaleX->set( mClipboardSize.mV[VX] ); + mCtrlScaleY->set( mClipboardSize.mV[VY] ); + mCtrlScaleZ->set( mClipboardSize.mV[VZ] ); + + sendScale(FALSE); +} + +void LLPanelObject::onPasteRot(const LLSD& data) +{ + if(!mHasRotClipboard) return; + + mCtrlRotX->set( mClipboardRot.mV[VX] ); + mCtrlRotY->set( mClipboardRot.mV[VY] ); + mCtrlRotZ->set( mClipboardRot.mV[VZ] ); + + sendRotation(FALSE); +} diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 8829f493fa..c1e0367b53 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -66,6 +66,13 @@ public: static void onCommitPhantom( LLUICtrl* ctrl, void* userdata); static void onCommitPhysics( LLUICtrl* ctrl, void* userdata); + void onCopyPos(const LLSD& data); + void onPastePos(const LLSD& data); + void onCopySize(const LLSD& data); + void onPasteSize(const LLSD& data); + void onCopyRot(const LLSD& data); + void onPasteRot(const LLSD& data); + static void onCommitParametric(LLUICtrl* ctrl, void* userdata); @@ -157,7 +164,18 @@ protected: LLComboBox *mCtrlSculptType; LLCheckBoxCtrl *mCtrlSculptMirror; LLCheckBoxCtrl *mCtrlSculptInvert; - + + LLButton *mBtnCopyPos; + LLButton *mBtnPastePos; + LLButton *mBtnCopySize; + LLButton *mBtnPasteSize; + LLButton *mBtnCopyRot; + LLButton *mBtnPasteRot; + + LLVector3 mClipboardPos; + LLVector3 mClipboardSize; + LLVector3 mClipboardRot; + LLVector3 mCurEulerDegrees; // to avoid sending rotation when not changed BOOL mIsPhysical; // to avoid sending "physical" when not changed BOOL mIsTemporary; // to avoid sending "temporary" when not changed @@ -167,6 +185,10 @@ protected: LLUUID mSculptTextureRevert; // so we can revert the sculpt texture on cancel U8 mSculptTypeRevert; // so we can revert the sculpt type on cancel + BOOL mHasPosClipboard; + BOOL mHasSizeClipboard; + BOOL mHasRotClipboard; + LLPointer mObject; LLPointer mRootObject; }; diff --git a/indra/newview/skins/default/textures/icons/Paste.png b/indra/newview/skins/default/textures/icons/Paste.png new file mode 100644 index 0000000000..10211df427 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Paste.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 2540ee148d..c3cc4e83d0 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -187,6 +187,7 @@ with the same filename but different name + diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index d9a15fed9e..81a207c023 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1446,6 +1446,21 @@ even though the user gets a free copy. text_enabled_color="1 0 0.3 .7" top_pad="5" width="87" /> + + Date: Thu, 11 Apr 2019 01:49:46 -0700 Subject: Added remaining physical properies to copy/paste --- indra/newview/llpanelobject.cpp | 63 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index c8a12f1d38..1e462876ee 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -33,6 +33,7 @@ #include "lleconomy.h" #include "llerror.h" #include "llfontgl.h" +#include "material_codes.h" // LL_MCODE_MASK #include "llpermissionsflags.h" #include "llstring.h" #include "llvolume.h" @@ -2261,7 +2262,29 @@ void LLPanelObject::onCopyParams(const LLSD& data) } // Physics - mParamsClipboard["physics_shape"] = objectp->getPhysicsShapeType(); + { + mParamsClipboard["physics_shape"] = objectp->getPhysicsShapeType(); + mParamsClipboard["physics_gravity"] = objectp->getPhysicsGravity(); + mParamsClipboard["physics_friction"] = objectp->getPhysicsFriction(); + mParamsClipboard["physics_density"] = objectp->getPhysicsDensity(); + mParamsClipboard["physics_restitution"] = objectp->getPhysicsRestitution(); + + U8 material_code = 0; + struct f : public LLSelectedTEGetFunctor + { + 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) + { + mParamsClipboard["physics_material"] = material_code; + } + } + } void LLPanelObject::onPasteParams(const LLSD& data) @@ -2335,9 +2358,43 @@ void LLPanelObject::onPasteParams(const LLSD& data) } // Physics - if (mParamsClipboard.has("physics_shape")) { - objectp->setPhysicsShapeType((U8)mParamsClipboard["physics_shape"].asInteger()); + if (mParamsClipboard.has("physics_shape")) + { + objectp->setPhysicsShapeType((U8)mParamsClipboard["physics_shape"].asInteger()); + } + if (mParamsClipboard.has("physics_material")) + { + U8 cur_material = objectp->getMaterial(); + U8 material = (U8)mParamsClipboard["physics_material"].asInteger() | (cur_material & ~LL_MCODE_MASK); + objectp->setMaterial(material); + objectp->sendMaterialUpdate(); + } + bool phys_update_flags = false; + if (mParamsClipboard.has("physics_gravity")) + { + objectp->setPhysicsGravity(mParamsClipboard["physics_gravity"].asReal()); + phys_update_flags = true; + } + if (mParamsClipboard.has("physics_friction")) + { + objectp->setPhysicsFriction(mParamsClipboard["physics_friction"].asReal()); + phys_update_flags = true; + } + if (mParamsClipboard.has("physics_density")) + { + objectp->setPhysicsDensity(mParamsClipboard["physics_density"].asReal()); + phys_update_flags = true; + } + if (mParamsClipboard.has("physics_restitution")) + { + objectp->setPhysicsRestitution(mParamsClipboard["physics_restitution"].asReal()); + phys_update_flags = true; + } + if (phys_update_flags) + { + objectp->updateFlags(TRUE); + } } // Parametrics -- cgit v1.2.3 From 41f5801aae25931b8e1a2db1b2eb9623efbc1f3e Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Tue, 16 Apr 2019 03:51:05 -0700 Subject: Added spotlight and phantom support to copy/paste Added paste options menu --- indra/newview/llpanelobject.cpp | 431 +++++++++++++-------- indra/newview/llpanelobject.h | 15 +- .../newview/skins/default/xui/en/floater_tools.xml | 23 +- 3 files changed, 290 insertions(+), 179 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1e462876ee..1809392ad0 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -50,6 +50,7 @@ #include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llmanipscale.h" +#include "llmenubutton.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -158,13 +159,13 @@ BOOL LLPanelObject::postBuild() mBtnCopyPos->setCommitCallback( boost::bind(&LLPanelObject::onCopyPos, this, _2 )); mBtnPastePos = getChild("paste_pos_btn"); mBtnPastePos->setCommitCallback( boost::bind(&LLPanelObject::onPastePos, this, _2 )); - + // Copy/paste size mBtnCopySize = getChild("copy_size_btn"); mBtnCopySize->setCommitCallback( boost::bind(&LLPanelObject::onCopySize, this, _2 )); mBtnPasteSize = getChild("paste_size_btn"); mBtnPasteSize->setCommitCallback( boost::bind(&LLPanelObject::onPasteSize, this, _2 )); - + // Copy/paste rot mBtnCopyRot = getChild("copy_rot_btn"); mBtnCopyRot->setCommitCallback( boost::bind(&LLPanelObject::onCopyRot, this, _2 )); @@ -176,6 +177,7 @@ BOOL LLPanelObject::postBuild() mBtnCopyParams->setCommitCallback( boost::bind(&LLPanelObject::onCopyParams, this, _2 )); mBtnPasteParams = getChild("paste_params_btn"); mBtnPasteParams->setCommitCallback( boost::bind(&LLPanelObject::onPasteParams, this, _2 )); + mBtnPasteMenu = getChild("patse_gear_btn"); //-------------------------------------------------------- @@ -316,8 +318,14 @@ LLPanelObject::LLPanelObject() mSizeChanged(FALSE), mHasPosClipboard(FALSE), mHasSizeClipboard(FALSE), - mHasRotClipboard(FALSE) + mHasRotClipboard(FALSE), + mPasteParametric(TRUE), + mPastePhysics(TRUE), + mPasteLight(TRUE) { + mEnableCallbackRegistrar.add("BuildObject.PasteCheckItem", boost::bind(&LLPanelObject::pasteCheckMenuItem, this, _2)); + mCommitCallbackRegistrar.add("BuildObject.PasteDoToSelected", boost::bind(&LLPanelObject::pasteDoMenuItem, this, _2)); + mEnableCallbackRegistrar.add("BuildObject.PasteEnable", boost::bind(&LLPanelObject::pasteEnabletMenuItem, this, _2)); } @@ -474,6 +482,7 @@ void LLPanelObject::getState( ) mBtnCopyParams->setEnabled( single_volume && enable_modify ); mBtnPasteParams->setEnabled( single_volume && enable_modify ); + mBtnPasteMenu->setEnabled( single_volume && enable_modify ); LLUUID owner_id; std::string owner_name; @@ -2136,9 +2145,13 @@ void LLPanelObject::onCopyParams(const LLSD& data) return; } + mParamsClipboard.clear(); + + mParamsClipboard["is_phantom"] = objectp->flagPhantom(); + mParamsClipboard["is_physical"] = objectp->flagUsePhysics(); + // Parametrics getVolumeParams(mClipboardVolumeParams); - mHasParamsClipboard = TRUE; LLVOVolume *volobjp = NULL; if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) @@ -2152,122 +2165,72 @@ void LLPanelObject::onCopyParams(const LLSD& data) LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); if (attributes) { - mParamsClipboard["lod"] = attributes->getSimulateLOD(); - mParamsClipboard["gav"] = attributes->getGravity(); - mParamsClipboard["ten"] = attributes->getTension(); - mParamsClipboard["fri"] = attributes->getAirFriction(); - mParamsClipboard["sen"] = attributes->getWindSensitivity(); + mParamsClipboard["flex"]["lod"] = attributes->getSimulateLOD(); + mParamsClipboard["flex"]["gav"] = attributes->getGravity(); + mParamsClipboard["flex"]["ten"] = attributes->getTension(); + mParamsClipboard["flex"]["fri"] = attributes->getAirFriction(); + mParamsClipboard["flex"]["sen"] = attributes->getWindSensitivity(); LLVector3 force = attributes->getUserForce(); - mParamsClipboard["forx"] = force.mV[0]; - mParamsClipboard["fory"] = force.mV[1]; - mParamsClipboard["forz"] = force.mV[2]; - mHasFlexiParam = TRUE; + mParamsClipboard["flex"]["forx"] = force.mV[0]; + mParamsClipboard["flex"]["fory"] = force.mV[1]; + mParamsClipboard["flex"]["forz"] = force.mV[2]; } } - else - { - mHasFlexiParam = FALSE; - } // Sculpted Prim - // User is allowed to copy if they could otherwise recreate it manually - // ie. User has full perm copy of the sculpted texture in their inventory, - // or is a default texture or library asset. if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) { LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID image_id = sculpt_params->getSculptTexture(); - BOOL allow_texture = FALSE; - if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) - || image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )) - || image_id == LLUUID(gSavedSettings.getString( "UIImgWhiteUUID" )) - || image_id == LLUUID(gSavedSettings.getString( "UIImgInvisibleUUID" )) - || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (canCopyTexture(texture_id)) { - allow_texture = TRUE; + LL_INFOS() << "copu texture " << LL_ENDL; + mParamsClipboard["sculpt"]["id"] = texture_id; } else { - LLUUID inventory_item_id; - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(image_id); - gInventory.collectDescendentsIf(LLUUID::null, - cats, - items, - LLInventoryModel::INCLUDE_TRASH, - asset_id_matches); - - if (items.size()) - { - // search for copyable version first - for (S32 i = 0; i < items.size(); i++) - { - LLInventoryItem* itemp = items[i]; - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) - { - inventory_item_id = itemp->getUUID(); - break; - } - } - } - if (inventory_item_id.notNull()) - { - LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); - if (itemp) - { - LLPermissions perm = itemp->getPermissions(); - if ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - allow_texture = TRUE; - } - } - } - } - if (allow_texture) - { - mParamsClipboard["sculptid"] = image_id; - } - else - { - mParamsClipboard["sculptid"] = LLUUID(SCULPT_DEFAULT_TEXTURE); + mParamsClipboard["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); } - mParamsClipboard["sculpt_type"] = sculpt_params->getSculptType(); - mHasSculptParam = TRUE; - } - else - { - mHasSculptParam = FALSE; + mParamsClipboard["sculpt"]["type"] = sculpt_params->getSculptType(); } // Light Source - // only captures basic settings if (volobjp && volobjp->getIsLight()) { - mParamsClipboard["Light Intensity"] = volobjp->getLightIntensity(); - mParamsClipboard["Light Radius"] = volobjp->getLightRadius(); - mParamsClipboard["Light Falloff"] = volobjp->getLightFalloff(); + mParamsClipboard["light"]["intensity"] = volobjp->getLightIntensity(); + mParamsClipboard["light"]["radius"] = volobjp->getLightRadius(); + mParamsClipboard["light"]["falloff"] = volobjp->getLightFalloff(); LLColor3 color = volobjp->getLightColor(); - mParamsClipboard["r"] = color.mV[0]; - mParamsClipboard["g"] = color.mV[1]; - mParamsClipboard["b"] = color.mV[2]; - mHasLightParam = TRUE; - } - else - { - mHasLightParam = FALSE; + mParamsClipboard["light"]["r"] = color.mV[0]; + mParamsClipboard["light"]["g"] = color.mV[1]; + mParamsClipboard["light"]["b"] = color.mV[2]; + + // Spotlight + if (volobjp->isLightSpotlight()) + { + LLUUID id = volobjp->getLightTextureID(); + if (id.notNull() && canCopyTexture(id)) + { + mParamsClipboard["spot"]["id"] = id; + LLVector3 spot_params = volobjp->getSpotLightParams(); + mParamsClipboard["spot"]["fov"] = spot_params.mV[0]; + mParamsClipboard["spot"]["focus"] = spot_params.mV[1]; + mParamsClipboard["spot"]["ambiance"] = spot_params.mV[2]; + } + } } + + // Physics { - mParamsClipboard["physics_shape"] = objectp->getPhysicsShapeType(); - mParamsClipboard["physics_gravity"] = objectp->getPhysicsGravity(); - mParamsClipboard["physics_friction"] = objectp->getPhysicsFriction(); - mParamsClipboard["physics_density"] = objectp->getPhysicsDensity(); - mParamsClipboard["physics_restitution"] = objectp->getPhysicsRestitution(); + mParamsClipboard["physics"]["shape"] = objectp->getPhysicsShapeType(); + mParamsClipboard["physics"]["gravity"] = objectp->getPhysicsGravity(); + mParamsClipboard["physics"]["friction"] = objectp->getPhysicsFriction(); + mParamsClipboard["physics"]["density"] = objectp->getPhysicsDensity(); + mParamsClipboard["physics"]["restitution"] = objectp->getPhysicsRestitution(); U8 material_code = 0; struct f : public LLSelectedTEGetFunctor @@ -2281,125 +2244,251 @@ void LLPanelObject::onCopyParams(const LLSD& data) // This should always be true since material should be per object. if (material_same) { - mParamsClipboard["physics_material"] = material_code; + mParamsClipboard["physics"]["material"] = material_code; } } - + + mHasParamsClipboard = TRUE; } void LLPanelObject::onPasteParams(const LLSD& data) { LLViewerObject* objectp = mObject; - if (!objectp) + if (!objectp || !mHasParamsClipboard) { return; } - // Flexi Prim - if (mHasFlexiParam && (objectp->getPCode() == LL_PCODE_VOLUME)) + LLVOVolume *volobjp = NULL; + if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) { - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - if (attributes) - { - LLFlexibleObjectData new_attributes; - new_attributes = *attributes; - - new_attributes.setSimulateLOD(mParamsClipboard["lod"].asInteger()); - new_attributes.setGravity(mParamsClipboard["gav"].asReal()); - new_attributes.setTension(mParamsClipboard["ten"].asReal()); - new_attributes.setAirFriction(mParamsClipboard["fri"].asReal()); - new_attributes.setWindSensitivity(mParamsClipboard["sen"].asReal()); - F32 fx = (F32)mParamsClipboard["forx"].asReal(); - F32 fy = (F32)mParamsClipboard["fory"].asReal(); - F32 fz = (F32)mParamsClipboard["forz"].asReal(); - LLVector3 force(fx,fy,fz); - new_attributes.setUserForce(force); - objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); - } + volobjp = (LLVOVolume *)objectp; } - // Sculpted Prim - if (mHasSculptParam) + // Light Source + if (mPasteLight && volobjp) { - LLSculptParams sculpt_params; - - if (mParamsClipboard.has("sculptid")) + if (mParamsClipboard.has("light")) { - sculpt_params.setSculptTexture(mParamsClipboard["sculptid"].asUUID(), (U8)mParamsClipboard["sculpt_type"].asInteger()); + volobjp->setIsLight(TRUE); + volobjp->setLightIntensity((F32)mParamsClipboard["light"]["intensity"].asReal()); + volobjp->setLightRadius((F32)mParamsClipboard["light"]["radius"].asReal()); + volobjp->setLightFalloff((F32)mParamsClipboard["light"]["falloff"].asReal()); + F32 r = (F32)mParamsClipboard["light"]["r"].asReal(); + F32 g = (F32)mParamsClipboard["light"]["g"].asReal(); + F32 b = (F32)mParamsClipboard["light"]["b"].asReal(); + volobjp->setLightColor(LLColor3(r,g,b)); } - objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); - } - else - { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) + if (mParamsClipboard.has("spot")) { - objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); + volobjp->setLightTextureID(mParamsClipboard["spot"]["id"]); + LLVector3 spot_params; + spot_params.mV[0] = (F32)mParamsClipboard["spot"]["fov"].asReal(); + spot_params.mV[1] = (F32)mParamsClipboard["spot"]["focus"].asReal(); + spot_params.mV[2] = (F32)mParamsClipboard["spot"]["ambiance"].asReal(); + volobjp->setSpotLightParams(spot_params); } } - // Light Source - if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + // Physics + if (mPastePhysics) { - LLVOVolume *volobjp = (LLVOVolume *)objectp; + bool is_root = objectp->isRoot(); - if (volobjp && mHasLightParam) - { - volobjp->setIsLight(TRUE); - volobjp->setLightIntensity((F32)mParamsClipboard["Light Intensity"].asReal()); - volobjp->setLightRadius((F32)mParamsClipboard["Light Radius"].asReal()); - volobjp->setLightFalloff((F32)mParamsClipboard["Light Falloff"].asReal()); - F32 r = (F32)mParamsClipboard["r"].asReal(); - F32 g = (F32)mParamsClipboard["g"].asReal(); - F32 b = (F32)mParamsClipboard["b"].asReal(); - volobjp->setLightColor(LLColor3(r,g,b)); - } - } + // Not sure if phantom should go under physics, but doesn't fit elsewhere + BOOL is_phantom = mParamsClipboard["is_phantom"].asBoolean() && is_root; + LLSelectMgr::getInstance()->selectionUpdatePhantom(is_phantom); - // Physics - { - if (mParamsClipboard.has("physics_shape")) - { - objectp->setPhysicsShapeType((U8)mParamsClipboard["physics_shape"].asInteger()); - } - if (mParamsClipboard.has("physics_material")) + BOOL is_physical = mParamsClipboard["is_physical"].asBoolean() && is_root; + LLSelectMgr::getInstance()->selectionUpdatePhysics(is_physical); + + if (mParamsClipboard.has("physics")) { + objectp->setPhysicsShapeType((U8)mParamsClipboard["physics"]["shape"].asInteger()); U8 cur_material = objectp->getMaterial(); U8 material = (U8)mParamsClipboard["physics_material"].asInteger() | (cur_material & ~LL_MCODE_MASK); + objectp->setMaterial(material); objectp->sendMaterialUpdate(); + objectp->setPhysicsGravity(mParamsClipboard["physics"]["gravity"].asReal()); + objectp->setPhysicsFriction(mParamsClipboard["physics"]["friction"].asReal()); + objectp->setPhysicsDensity(mParamsClipboard["physics"]["density"].asReal()); + objectp->setPhysicsRestitution(mParamsClipboard["physics"]["restitution"].asReal()); + objectp->updateFlags(TRUE); } - bool phys_update_flags = false; - if (mParamsClipboard.has("physics_gravity")) + } + + // Parametrics + if(mPasteParametric) + { + // Sculpted Prim + if (mParamsClipboard.has("sculpt")) { - objectp->setPhysicsGravity(mParamsClipboard["physics_gravity"].asReal()); - phys_update_flags = true; + LLSculptParams sculpt_params; + LLUUID sculpt_id = mParamsClipboard["sculpt"]["id"].asUUID(); + U8 sculpt_type = (U8)mParamsClipboard["sculpt"]["type"].asInteger(); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); + objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); } - if (mParamsClipboard.has("physics_friction")) + else { - objectp->setPhysicsFriction(mParamsClipboard["physics_friction"].asReal()); - phys_update_flags = true; + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if (sculpt_params) + { + objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); + } } - if (mParamsClipboard.has("physics_density")) + + // Flexi Params + if (mParamsClipboard.has("flex")) + { + 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(mParamsClipboard["flex"]["lod"].asInteger()); + new_attributes.setGravity(mParamsClipboard["flex"]["gav"].asReal()); + new_attributes.setTension(mParamsClipboard["flex"]["ten"].asReal()); + new_attributes.setAirFriction(mParamsClipboard["flex"]["fri"].asReal()); + new_attributes.setWindSensitivity(mParamsClipboard["flex"]["sen"].asReal()); + F32 fx = (F32)mParamsClipboard["flex"]["forx"].asReal(); + F32 fy = (F32)mParamsClipboard["flex"]["fory"].asReal(); + F32 fz = (F32)mParamsClipboard["flex"]["forz"].asReal(); + LLVector3 force(fx,fy,fz); + new_attributes.setUserForce(force); + objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); + } + } + + objectp->updateVolume(mClipboardVolumeParams); + } +} + +bool LLPanelObject::pasteCheckMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("Parametric" == command) + { + return mPasteParametric; + } + if ("Physics" == command) + { + return mPastePhysics; + } + if ("Light" == command) + { + return mPasteLight; + } + + return false; +} + +void LLPanelObject::pasteDoMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("Parametric" == command) + { + mPasteParametric = !mPasteParametric; + } + if ("Physics" == command) + { + mPastePhysics = !mPastePhysics; + } + if ("Light" == command) + { + mPasteLight = !mPasteLight; + } +} + +bool LLPanelObject::pasteEnabletMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // Keep at least one option enabled + if (mPasteParametric + mPastePhysics + mPasteLight == 1) + { + if ("Parametric" == command && mPasteParametric) { - objectp->setPhysicsDensity(mParamsClipboard["physics_density"].asReal()); - phys_update_flags = true; + return false; } - if (mParamsClipboard.has("physics_restitution")) + if ("Physics" == command && mPastePhysics) { - objectp->setPhysicsRestitution(mParamsClipboard["physics_restitution"].asReal()); - phys_update_flags = true; + return false; } - if (phys_update_flags) + if ("Light" == command && mPasteLight) { - objectp->updateFlags(TRUE); + return false; } } - // Parametrics - if(mHasParamsClipboard) + return true; +} + +// User is allowed to copy if they could otherwise recreate it manually +// ie. User has full perm copy of the sculpted texture in their inventory, +// or is a default texture or library asset. +bool LLPanelObject::canCopyTexture(LLUUID image_id) +{ + // Library asset or default texture + if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) + || image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )) + || image_id == LLUUID(gSavedSettings.getString( "UIImgWhiteUUID" )) + || image_id == LLUUID(gSavedSettings.getString( "UIImgInvisibleUUID" )) + || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) { - objectp->updateVolume(mClipboardVolumeParams); + return true; + } + + // LLUUID inventory_item_id; + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(image_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + if (items.size()) + { + // search for copyable version first + for (S32 i = 0; i < items.size(); i++) + { + LLInventoryItem* itemp = items[i]; + LLPermissions item_permissions = itemp->getPermissions(); + // if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + if (item_permissions.allowCopyBy(gAgent.getID())) + { + // inventory_item_id = itemp->getUUID(); + // break; + return true; + } + } } + + // if (inventory_item_id.notNull()) + // { + // LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); + // if (itemp) + // { + // if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + // // LLPermissions perm = itemp->getPermissions(); + // // if ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) + // { + // // User has full perm copy of texture + // return true; + // } + // } + // } + + return false; } diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 46725a80e4..7fa728ea57 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLTextBox; class LLUICtrl; class LLButton; +class LLMenuButton; class LLViewerObject; class LLComboBox; class LLColorSwatchCtrl; @@ -84,6 +85,10 @@ public: BOOL onDropSculpt(LLInventoryItem* item); static void onCommitSculptType( LLUICtrl *ctrl, void* userdata); + bool pasteCheckMenuItem(const LLSD& userdata); + void pasteDoMenuItem(const LLSD& userdata); + bool pasteEnabletMenuItem(const LLSD& userdata); + protected: void getState(); @@ -97,6 +102,8 @@ protected: void sendSculpt(); void getVolumeParams(LLVolumeParams& volume_params); + + bool canCopyTexture(LLUUID image_id); protected: // Per-object options @@ -164,6 +171,7 @@ protected: LLButton *mBtnPasteRot; LLButton *mBtnCopyParams; LLButton *mBtnPasteParams; + LLMenuButton *mBtnPasteMenu; LLCheckBoxCtrl *mCheckLock; LLCheckBoxCtrl *mCheckPhysics; @@ -196,9 +204,10 @@ protected: LLSD mParamsClipboard; LLVolumeParams mClipboardVolumeParams; BOOL mHasParamsClipboard; - BOOL mHasFlexiParam; - BOOL mHasSculptParam; - BOOL mHasLightParam; + + BOOL mPasteParametric; + BOOL mPastePhysics; + BOOL mPasteLight; LLPointer mObject; LLPointer mRootObject; diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 1e2846d943..8a7272d9e4 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1696,25 +1696,38 @@ even though the user gets a free copy. --> + Date: Wed, 17 Apr 2019 02:41:33 -0700 Subject: Added translation support for build tools paste buttons tooltips --- indra/newview/llpanelobject.cpp | 65 +++++++++------------- .../newview/skins/default/xui/en/floater_tools.xml | 12 ++++ 2 files changed, 37 insertions(+), 40 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1809392ad0..8a51007af7 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2050,19 +2050,17 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } -void copy_vector_to_clipboard(const LLVector3& vec) -{ - std::string stringVec = llformat("<%g, %g, %g>", vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); -} - void LLPanelObject::onCopyPos(const LLSD& data) { - mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); + mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); - copy_vector_to_clipboard(mClipboardPos); + std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + + LLStringUtil::format_map_t args; + args["VALUE"] = stringVec; + mBtnPastePos->setToolTip(getString("paste_position", args)); - mBtnPastePos->setToolTip(llformat("Paste Position\n<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ])); mBtnPastePos->setEnabled(TRUE); mHasPosClipboard = TRUE; @@ -2070,11 +2068,15 @@ void LLPanelObject::onCopyPos(const LLSD& data) void LLPanelObject::onCopySize(const LLSD& data) { - mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); + mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); + + std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - copy_vector_to_clipboard(mClipboardSize); + LLStringUtil::format_map_t args; + args["VALUE"] = stringVec; + mBtnPasteSize->setToolTip(getString("paste_size", args)); - mBtnPasteSize->setToolTip(llformat("Paste Size\n<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ])); mBtnPasteSize->setEnabled(TRUE); mHasSizeClipboard = TRUE; @@ -2082,11 +2084,15 @@ void LLPanelObject::onCopySize(const LLSD& data) void LLPanelObject::onCopyRot(const LLSD& data) { - mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); + mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); + + std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - copy_vector_to_clipboard(mClipboardRot); + LLStringUtil::format_map_t args; + args["VALUE"] = stringVec; + mBtnPasteRot->setToolTip(getString("paste_rotation", args)); - mBtnPasteRot->setToolTip(llformat("Paste Rotation\n<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ])); mBtnPasteRot->setEnabled(TRUE); mHasRotClipboard = TRUE; @@ -2221,8 +2227,6 @@ void LLPanelObject::onCopyParams(const LLSD& data) } } } - - // Physics { @@ -2373,7 +2377,7 @@ void LLPanelObject::onPasteParams(const LLSD& data) bool LLPanelObject::pasteCheckMenuItem(const LLSD& userdata) { - std::string command = userdata.asString(); + std::string command = userdata.asString(); if ("Parametric" == command) { @@ -2388,12 +2392,12 @@ bool LLPanelObject::pasteCheckMenuItem(const LLSD& userdata) return mPasteLight; } - return false; + return false; } void LLPanelObject::pasteDoMenuItem(const LLSD& userdata) { - std::string command = userdata.asString(); + std::string command = userdata.asString(); if ("Parametric" == command) { @@ -2411,7 +2415,7 @@ void LLPanelObject::pasteDoMenuItem(const LLSD& userdata) bool LLPanelObject::pasteEnabletMenuItem(const LLSD& userdata) { - std::string command = userdata.asString(); + std::string command = userdata.asString(); // Keep at least one option enabled if (mPasteParametric + mPastePhysics + mPasteLight == 1) @@ -2457,7 +2461,6 @@ bool LLPanelObject::canCopyTexture(LLUUID image_id) items, LLInventoryModel::INCLUDE_TRASH, asset_id_matches); - if (items.size()) { // search for copyable version first @@ -2465,30 +2468,12 @@ bool LLPanelObject::canCopyTexture(LLUUID image_id) { LLInventoryItem* itemp = items[i]; LLPermissions item_permissions = itemp->getPermissions(); - // if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) if (item_permissions.allowCopyBy(gAgent.getID())) { - // inventory_item_id = itemp->getUUID(); - // break; return true; } } } - // if (inventory_item_id.notNull()) - // { - // LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); - // if (itemp) - // { - // if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) - // // LLPermissions perm = itemp->getPermissions(); - // // if ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - // { - // // User has full perm copy of texture - // return true; - // } - // } - // } - return false; } diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 8a7272d9e4..150d3d9804 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1387,6 +1387,18 @@ even though the user gets a free copy. name="Object" top="16" width="295"> + +Paste Position +[VALUE] + + +Paste Size +[VALUE] + + +Paste Rotation +[VALUE] + Date: Thu, 18 Apr 2019 23:39:12 -0700 Subject: Build tools paste options menu --- .../skins/default/xui/en/menu_build_paste.xml | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 indra/newview/skins/default/xui/en/menu_build_paste.xml (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_build_paste.xml b/indra/newview/skins/default/xui/en/menu_build_paste.xml new file mode 100644 index 0000000000..f63362dabf --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_build_paste.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 733f799c4359d32778b5f345ae434152467334bc Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Fri, 6 Sep 2019 20:46:23 -0700 Subject: Cleanup object copy/paste functions --- indra/newview/llpanelobject.cpp | 37 +++++++++++----------- indra/newview/llpanelobject.h | 19 ++++++----- .../newview/skins/default/xui/en/floater_tools.xml | 4 +-- 3 files changed, 30 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 8a51007af7..1a0c2c86eb 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -156,28 +156,28 @@ BOOL LLPanelObject::postBuild() // Copy/paste pos mBtnCopyPos = getChild("copy_pos_btn"); - mBtnCopyPos->setCommitCallback( boost::bind(&LLPanelObject::onCopyPos, this, _2 )); + mBtnCopyPos->setCommitCallback(boost::bind(&LLPanelObject::onCopyPos, this)); mBtnPastePos = getChild("paste_pos_btn"); - mBtnPastePos->setCommitCallback( boost::bind(&LLPanelObject::onPastePos, this, _2 )); + mBtnPastePos->setCommitCallback(boost::bind(&LLPanelObject::onPastePos, this)); // Copy/paste size mBtnCopySize = getChild("copy_size_btn"); - mBtnCopySize->setCommitCallback( boost::bind(&LLPanelObject::onCopySize, this, _2 )); + mBtnCopySize->setCommitCallback(boost::bind(&LLPanelObject::onCopySize, this)); mBtnPasteSize = getChild("paste_size_btn"); - mBtnPasteSize->setCommitCallback( boost::bind(&LLPanelObject::onPasteSize, this, _2 )); + mBtnPasteSize->setCommitCallback(boost::bind(&LLPanelObject::onPasteSize, this)); // Copy/paste rot mBtnCopyRot = getChild("copy_rot_btn"); - mBtnCopyRot->setCommitCallback( boost::bind(&LLPanelObject::onCopyRot, this, _2 )); + mBtnCopyRot->setCommitCallback(boost::bind(&LLPanelObject::onCopyRot, this)); mBtnPasteRot = getChild("paste_rot_btn"); - mBtnPasteRot->setCommitCallback( boost::bind(&LLPanelObject::onPasteRot, this, _2 ));; + mBtnPasteRot->setCommitCallback(boost::bind(&LLPanelObject::onPasteRot, this));; // Copy/paste obj prams mBtnCopyParams = getChild("copy_params_btn"); - mBtnCopyParams->setCommitCallback( boost::bind(&LLPanelObject::onCopyParams, this, _2 )); + mBtnCopyParams->setCommitCallback(boost::bind(&LLPanelObject::onCopyParams, this)); mBtnPasteParams = getChild("paste_params_btn"); - mBtnPasteParams->setCommitCallback( boost::bind(&LLPanelObject::onPasteParams, this, _2 )); - mBtnPasteMenu = getChild("patse_gear_btn"); + mBtnPasteParams->setCommitCallback(boost::bind(&LLPanelObject::onPasteParams, this)); + mBtnPasteMenu = getChild("paste_gear_btn"); //-------------------------------------------------------- @@ -2050,7 +2050,7 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } -void LLPanelObject::onCopyPos(const LLSD& data) +void LLPanelObject::onCopyPos() { mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); @@ -2066,7 +2066,7 @@ void LLPanelObject::onCopyPos(const LLSD& data) mHasPosClipboard = TRUE; } -void LLPanelObject::onCopySize(const LLSD& data) +void LLPanelObject::onCopySize() { mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); @@ -2082,7 +2082,7 @@ void LLPanelObject::onCopySize(const LLSD& data) mHasSizeClipboard = TRUE; } -void LLPanelObject::onCopyRot(const LLSD& data) +void LLPanelObject::onCopyRot() { mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); @@ -2098,7 +2098,7 @@ void LLPanelObject::onCopyRot(const LLSD& data) mHasRotClipboard = TRUE; } -void LLPanelObject::onPastePos(const LLSD& data) +void LLPanelObject::onPastePos() { if(!mHasPosClipboard) return; @@ -2117,7 +2117,7 @@ void LLPanelObject::onPastePos(const LLSD& data) sendPosition(FALSE); } -void LLPanelObject::onPasteSize(const LLSD& data) +void LLPanelObject::onPasteSize() { if(!mHasSizeClipboard) return; @@ -2132,7 +2132,7 @@ void LLPanelObject::onPasteSize(const LLSD& data) sendScale(FALSE); } -void LLPanelObject::onPasteRot(const LLSD& data) +void LLPanelObject::onPasteRot() { if(!mHasRotClipboard) return; @@ -2143,7 +2143,7 @@ void LLPanelObject::onPasteRot(const LLSD& data) sendRotation(FALSE); } -void LLPanelObject::onCopyParams(const LLSD& data) +void LLPanelObject::onCopyParams() { LLViewerObject* objectp = mObject; if (!objectp) @@ -2255,7 +2255,7 @@ void LLPanelObject::onCopyParams(const LLSD& data) mHasParamsClipboard = TRUE; } -void LLPanelObject::onPasteParams(const LLSD& data) +void LLPanelObject::onPasteParams() { LLViewerObject* objectp = mObject; if (!objectp || !mHasParamsClipboard) @@ -2286,7 +2286,7 @@ void LLPanelObject::onPasteParams(const LLSD& data) if (mParamsClipboard.has("spot")) { - volobjp->setLightTextureID(mParamsClipboard["spot"]["id"]); + volobjp->setLightTextureID(mParamsClipboard["spot"]["id"].asUUID()); LLVector3 spot_params; spot_params.mV[0] = (F32)mParamsClipboard["spot"]["fov"].asReal(); spot_params.mV[1] = (F32)mParamsClipboard["spot"]["focus"].asReal(); @@ -2440,6 +2440,7 @@ bool LLPanelObject::pasteEnabletMenuItem(const LLSD& userdata) // User is allowed to copy if they could otherwise recreate it manually // ie. User has full perm copy of the sculpted texture in their inventory, // or is a default texture or library asset. +// Static bool LLPanelObject::canCopyTexture(LLUUID image_id) { // Library asset or default texture diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 7fa728ea57..7161f51c73 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -67,14 +67,14 @@ public: static void onCommitPhantom( LLUICtrl* ctrl, void* userdata); static void onCommitPhysics( LLUICtrl* ctrl, void* userdata); - void onCopyPos(const LLSD& data); - void onPastePos(const LLSD& data); - void onCopySize(const LLSD& data); - void onPasteSize(const LLSD& data); - void onCopyRot(const LLSD& data); - void onPasteRot(const LLSD& data); - void onCopyParams(const LLSD& data); - void onPasteParams(const LLSD& data); + void onCopyPos(); + void onPastePos(); + void onCopySize(); + void onPasteSize(); + void onCopyRot(); + void onPasteRot(); + void onCopyParams(); + void onPasteParams(); static void onCommitParametric(LLUICtrl* ctrl, void* userdata); @@ -88,6 +88,7 @@ public: bool pasteCheckMenuItem(const LLSD& userdata); void pasteDoMenuItem(const LLSD& userdata); bool pasteEnabletMenuItem(const LLSD& userdata); + static bool canCopyTexture(LLUUID image_id); protected: void getState(); @@ -102,8 +103,6 @@ protected: void sendSculpt(); void getVolumeParams(LLVolumeParams& volume_params); - - bool canCopyTexture(LLUUID image_id); protected: // Per-object options diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 150d3d9804..3032ad50b3 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1737,7 +1737,7 @@ Paste Rotation image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="5" - name="patse_gear_btn" + name="paste_gear_btn" tool_tip="Paste options" width="31"/> - Date: Tue, 1 Oct 2019 15:44:05 +0300 Subject: SL-11944 FIXED [Project Copy/Paste] The prim's shape can be changed by pasting empty parameters --- indra/newview/llpanelobject.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1e462876ee..3c41a4bce4 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -314,6 +314,7 @@ LLPanelObject::LLPanelObject() mSculptTextureRevert(LLUUID::null), mSculptTypeRevert(0), mSizeChanged(FALSE), + mHasParamsClipboard(FALSE), mHasPosClipboard(FALSE), mHasSizeClipboard(FALSE), mHasRotClipboard(FALSE) @@ -473,7 +474,7 @@ void LLPanelObject::getState( ) mBtnPasteRot->setEnabled( enable_rotate && mHasRotClipboard ); mBtnCopyParams->setEnabled( single_volume && enable_modify ); - mBtnPasteParams->setEnabled( single_volume && enable_modify ); + mBtnPasteParams->setEnabled( single_volume && enable_modify && mHasParamsClipboard ); LLUUID owner_id; std::string owner_name; @@ -2284,13 +2285,13 @@ void LLPanelObject::onCopyParams(const LLSD& data) mParamsClipboard["physics_material"] = material_code; } } - + mBtnPasteParams->setEnabled(TRUE); } void LLPanelObject::onPasteParams(const LLSD& data) { LLViewerObject* objectp = mObject; - if (!objectp) + if (!objectp || !mHasParamsClipboard) { return; } -- cgit v1.2.3 From ce48cb4303c10dbc9d3044271035153569226040 Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Sun, 6 Oct 2019 16:09:56 -0700 Subject: [Project Copy/Paste] Simplified texture copy check --- indra/newview/llpanelobject.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1a0c2c86eb..e53f03785f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2437,12 +2437,13 @@ bool LLPanelObject::pasteEnabletMenuItem(const LLSD& userdata) return true; } -// User is allowed to copy if they could otherwise recreate it manually -// ie. User has full perm copy of the sculpted texture in their inventory, -// or is a default texture or library asset. // Static bool LLPanelObject::canCopyTexture(LLUUID image_id) { + // User is allowed to copy a texture if: + // library asset or default texture, + // or full perm asset exists in user's inventory + // Library asset or default texture if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) || image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )) @@ -2452,8 +2453,8 @@ bool LLPanelObject::canCopyTexture(LLUUID image_id) { return true; } - - // LLUUID inventory_item_id; + + // Search for a full perm asset LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLAssetIDMatches asset_id_matches(image_id); @@ -2464,12 +2465,10 @@ bool LLPanelObject::canCopyTexture(LLUUID image_id) asset_id_matches); if (items.size()) { - // search for copyable version first for (S32 i = 0; i < items.size(); i++) { - LLInventoryItem* itemp = items[i]; - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowCopyBy(gAgent.getID())) + LLViewerInventoryItem* itemp = items[i]; + if (itemp->getIsFullPerm()) { return true; } -- cgit v1.2.3 From 1e1707d532560583744bb877adfed11864f2db31 Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Mon, 14 Oct 2019 20:35:44 -0700 Subject: [Project Copy/Paste] Texture support --- indra/newview/llpanelface.cpp | 482 ++++++++++++++++++++- indra/newview/llpanelface.h | 27 +- .../skins/default/xui/en/menu_texture_paste.xml | 70 +++ .../skins/default/xui/en/panel_tools_texture.xml | 55 ++- 4 files changed, 618 insertions(+), 16 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_texture_paste.xml (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 5e6a44c09d..29994253c4 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@ #include "llfontgl.h" // project includes +#include "llagent.h" // gAgent #include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -45,10 +46,14 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" // gInventory #include "lllineeditor.h" #include "llmaterialmgr.h" #include "llmediaentry.h" +#include "llmenubutton.h" #include "llnotificationsutil.h" +#include "llpanelobject.h" // LLPanelObject::canCopyTexture #include "llradiogroup.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -295,7 +300,18 @@ BOOL LLPanelFace::postBuild() { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - + + mBtnCopyFaces = getChild("copy_face_btn"); + if(mBtnCopyFaces) + { + BtnCopyFaces->setCommitCallback(boost::bind(&LLPanelFace::onCopyFaces, this)); + } + mBtnPasteFaces = getChild("paste_face_btn"); + if (mBtnPasteFaces) + { + mBtnPasteFaces->setCommitCallback(boost::bind(&LLPanelFace::onPasteFaces, this)); + } + mBtnPasteMenu = getChild("paste_face_gear_btn"); clearCtrls(); @@ -304,9 +320,21 @@ BOOL LLPanelFace::postBuild() LLPanelFace::LLPanelFace() : LLPanel(), - mIsAlpha(false) + mIsAlpha(false), + mPasteColor(TRUE), + mPasteAlpha(TRUE), + mPasteGlow(TRUE), + mPasteDiffuse(TRUE), + mPasteNormal(TRUE), + mPasteSpecular(TRUE), + mPasteMapping(TRUE), + mPasteMedia(TRUE) { USE_TEXTURE = LLTrans::getString("use_texture"); + + mEnableCallbackRegistrar.add("BuildFace.PasteCheckItem", boost::bind(&LLPanelFace::pasteCheckMenuItem, this, _2)); + mCommitCallbackRegistrar.add("BuildFace.PasteDoToSelected", boost::bind(&LLPanelFace::pasteDoMenuItem, this, _2)); + mEnableCallbackRegistrar.add("BuildFace.PasteEnable", boost::bind(&LLPanelFace::pasteEnabletMenuItem, this, _2)); } @@ -1407,6 +1435,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (selected_count == 1); + mBtnCopyFaces->setEnabled(editable && single_volume); + mBtnPasteFaces->setEnabled(editable && (mClipboard.size() > 0)); + mBtnPasteMenu->setEnabled(editable); + // Set variable values for numeric expressions LLCalc* calcp = LLCalc::getInstance(); calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal()); @@ -1602,8 +1636,6 @@ void LLPanelFace::updateVisibility() getChildView("bumpyRot")->setVisible(show_bumpiness); getChildView("bumpyOffsetU")->setVisible(show_bumpiness); getChildView("bumpyOffsetV")->setVisible(show_bumpiness); - - } // static @@ -2681,3 +2713,445 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic } max_diff_repeats_func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats ); } + +static LLSD texture_clipboard; + +void LLPanelFace::onCopyFaces() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if( !objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + return; + } + + mClipboard.clear(); + + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + LLSD te_data; + + te_data["te"] = tep->asLLSD(); + te_data["te"]["glow"] = tep->getGlow(); + te_data["te"]["shiny"] = tep->getShiny(); + + if (te_data["te"].has("imageid")) + { + LLUUID id = te_data["te"]["imageid"].asUUID(); + if (id.isNull() || !LLPanelObject::canCopyTexture(id)) + { + te_data["te"].erase("imageid"); + te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); + } + // else + // { + // te_data["te"]["imageid"] = canCopyTexture(te_data["te"]["imageid"].asUUID()); + // } + } + + LLMaterialPtr material_ptr = tep->getMaterialParams(); + if (!material_ptr.isNull()) + { + LLSD mat_data; + + mat_data["NormMap"] = material_ptr->getNormalID(); + mat_data["SpecMap"] = material_ptr->getSpecularID(); + + mat_data["NormRepX"] = material_ptr->getNormalRepeatX(); + mat_data["NormRepY"] = material_ptr->getNormalRepeatY(); + mat_data["NormOffX"] = material_ptr->getNormalOffsetX(); + mat_data["NormOffY"] = material_ptr->getNormalOffsetY(); + mat_data["NormRot"] = material_ptr->getNormalRotation(); + + mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX(); + mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY(); + mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX(); + mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY(); + mat_data["SpecRot"] = material_ptr->getSpecularRotation(); + + mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue(); + mat_data["SpecExp"] = material_ptr->getSpecularLightExponent(); + mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity(); + mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff(); + mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode(); + + // Replace no-copy textures, destination texture will get used instead if available + if (mat_data.has("NormMap")) + { + LLUUID id = te_data["material"]["NormMap"].asUUID(); + if (id.notNull() && !LLPanelObject::canCopyTexture(id)) + { + mat_data["NormMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); + mat_data["NormMapNoCopy"] = true; + } + + } + if (mat_data.has("SpecMap")) + { + LLUUID id = te_data["material"]["SpecMap"].asUUID(); + if (id.notNull() && !LLPanelObject::canCopyTexture(id)) + { + mat_data["SpecMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); + mat_data["SpecMapNoCopy"] = true; + } + + } + + te_data["material"] = mat_data; + } + + //*TODO: Media + + mClipboard.append(te_data); + } + } + } +} + +void LLPanelFace::pasteFace(LLViewerObject* objectp, S32 te) +{ + LLSD te_data; + if (mClipboard.size() == 1) + { + te_data = *(mClipboard.beginArray()); + } + else if (mClipboard[te]) + { + te_data = mClipboard[te]; + } + else + { + return; + } + + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + if (te_data.has("te")) + { + // Texture + if (mPasteDiffuse) + { + // Replace no-copy texture with target's + if (!te_data["te"].has("imageid")) + { + te_data["te"]["imageid"] = tep->getID(); + } + const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); + LLViewerInventoryItem* item = gInventory.getItem(imageid); + if (item) + { + if (te == -1) // all faces + { + LLToolDragAndDrop::dropTextureAllFaces(objectp, + item, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + else // one face + { + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + item, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + } + else // not an inventory item + { + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + objectp->setTEImage(U8(te), image); + } + } + + // Color / Alpha + if ((mPasteColor || mPasteAlpha) && te_data.has("colors")) + { + LLColor4 color = objectp->getTE(te)->getColor(); + + LLColor4 clip_color; + clip_color.setValue(te_data["colors"]); + + // Color + if (mPasteColor) + { + color.mV[VRED] = clip_color.mV[VRED]; + color.mV[VGREEN] = clip_color.mV[VGREEN]; + color.mV[VBLUE] = clip_color.mV[VBLUE]; + } + + // Alpha + if (mPasteAlpha) + { + color.mV[VALPHA] = clip_color.mV[VALPHA]; + } + + objectp->setTEColor(te, color); + } + + // Glow + if (mPasteGlow && te_data.has("glow")) + { + objectp->setTEGlow(te, (F32)te_data["glow"].asReal()); + } + + // Texture map + if (mPasteMapping) + { + if (te_data.has("scales") && te_data.has("scalet")) + { + objectp->setTEScale(te, (F32)te_data["scales"].asReal(), (F32)te_data["scalet"].asReal()); + } + if (te_data.has("offsets") && te_data.has("offsett")) + { + objectp->setTEOffset(te, (F32)te_data["offsets"].asReal(), (F32)te_data["offsett"].asReal()); + } + if (te_data.has("imagerot")) + { + objectp->setTERotation(te, (F32)te_data["imagerot"].asReal()); + } + } + + // Media + if (mPasteMedia && te_data.has("media")) + { + //*TODO + } + else + { + // // Keep media flags on destination unchanged + // // Media is handled later + // if (te_data["te"].has("media_flags")) + // { + // te_data["te"]["media_flags"] = tep->getMediaTexGen(); + // } + } + } + + if (te_data.has("material")) + { + LLUUID object_id = objectp->getID(); + + LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + + if (mPasteNormal) + { + // Replace placeholders with target's + if (te_data["material"].has("NormMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getNormalID(); + if (id.notNull()) + { + te_data["material"]["NormMap"] = id; + } + } + } + LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id); + } + + if (mPasteSpecular) + { + // Replace placeholders with target's + if (te_data["material"].has("SpecMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getSpecularID(); + if (id.notNull()) + { + te_data["material"]["SpecMap"] = id; + } + } + } + LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id); + LLColor4 spec_color(te_data["material"]["SpecColor"]); + LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); + LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); + LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te), object_id; + LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + if (te_data.has("shiny")) + { + objectp->setTEShiny(te, (U8)te_data["shiny"].asInteger()); + } + } + } + } +} + +struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor +{ + LLPanelFacePasteTexFunctor(LLPanelFace* panel) : + mPanelFace(panel){} + + virtual bool apply(LLViewerObject* objectp, S32 te) + { + mPanelFace->pasteFace(objectp, te); + return true; + } +private: + LLPanelFace *mPanelFace; +}; + +void LLPanelFace::onPasteFaces() +{ + LLPanelFacePasteTexFunctor paste_func(this); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&paste_func); + + LLPanelFaceSendFunctor sendfunc; + LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); +} + +bool LLPanelFace::pasteCheckMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("Color" == command) + { + return mPasteColor; + } + if ("Transparency" == command) + { + return mPasteAlpha; + } + if ("Glow" == command) + { + return mPasteGlow; + } + if ("Diffuse" == command) + { + return mPasteDiffuse; + } + if ("Normal" == command) + { + return mPasteNormal; + } + if ("Specular" == command) + { + return mPasteSpecular; + } + if ("Mapping" == command) + { + return mPasteMapping; + } + if ("Media" == command) + { + return mPasteMedia; + } + + return false; +} + +void LLPanelFace::pasteDoMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("Color" == command) + { + mPasteColor = !mPasteColor; + } + if ("Transparency" == command) + { + mPasteAlpha = !mPasteAlpha; + } + if ("Glow" == command) + { + mPasteGlow = !mPasteGlow; + } + if ("Diffuse" == command) + { + mPasteDiffuse = !mPasteDiffuse; + } + if ("Normal" == command) + { + mPasteNormal = !mPasteNormal; + } + if ("Specular" == command) + { + mPasteSpecular = !mPasteSpecular; + } + if ("Mapping" == command) + { + mPasteMapping = !mPasteMapping; + } + if ("Media" == command) + { + mPasteMedia = !mPasteMedia; + } +} + +bool LLPanelFace::pasteEnabletMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // Keep at least one option enabled + S32 num_enabled = mPasteColor + + mPasteAlpha + + mPasteGlow + + mPasteDiffuse + + mPasteNormal + + mPasteSpecular + + mPasteMapping + + mPasteMedia; + if ( num_enabled == 1) + { + if ("Color" == command && mPasteColor) + { + return false; + } + if ("Transparency" == command && mPasteAlpha) + { + return false; + } + if ("Glow" == command && mPasteGlow) + { + return false; + } + if ("Diffuse" == command && mPasteDiffuse) + { + return false; + } + if ("Normal" == command && mPasteNormal) + { + return false; + } + if ("Specular" == command && mPasteSpecular) + { + return false; + } + if ("Mapping" == command && mPasteMapping) + { + return false; + } + if ("Media" == command && mPasteMedia) + { + return false; + } + } + + return true; +} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 0b40d7d41a..064262a312 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,6 +47,7 @@ class LLUICtrl; class LLViewerObject; class LLFloater; class LLMaterialID; +class LLMenuButton; // Represents an edit for use in replicating the op across one or more materials in the selection set. // @@ -113,6 +114,8 @@ public: LLRender::eTexIndex getTextureChannelToEdit(); + void pasteFace(LLViewerObject* object, S32 te); + protected: void getState(); @@ -203,9 +206,13 @@ protected: static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); static void onClickAutoFix(void*); - static F32 valueGlow(LLViewerObject* object, S32 face); + void onCopyFaces(); + void onPasteFaces(); + bool pasteCheckMenuItem(const LLSD& userdata); + void pasteDoMenuItem(const LLSD& userdata); + bool pasteEnabletMenuItem(const LLSD& userdata); - + static F32 valueGlow(LLViewerObject* object, S32 face); private: @@ -232,6 +239,20 @@ private: F32 getCurrentShinyOffsetU(); F32 getCurrentShinyOffsetV(); + LLButton *mBtnCopyFaces; + LLButton *mBtnPasteFaces; + LLMenuButton *mBtnPasteMenu; + + LLSD mClipboard; + BOOL mPasteColor; + BOOL mPasteAlpha; + BOOL mPasteGlow; + BOOL mPasteDiffuse; + BOOL mPasteNormal; + BOOL mPasteSpecular; + BOOL mPasteMapping; + BOOL mPasteMedia; + // Update visibility of controls to match current UI mode // (e.g. materials vs media editing) // @@ -495,6 +516,8 @@ public: DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID); DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID); DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor); + + DEF_EDIT_MAT_STATE(LLSD, const LLSD&, fromLLSD); }; class LLSelectedTE diff --git a/indra/newview/skins/default/xui/en/menu_texture_paste.xml b/indra/newview/skins/default/xui/en/menu_texture_paste.xml new file mode 100644 index 0000000000..be6535b989 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_texture_paste.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 67b99ca588..a658676b51 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -43,7 +43,7 @@ follows="left|top" height="10" layout="topleft" - left_pad="15" + left_pad="10" name="color trans" text_readonly_color="LabelDisabledColor" top="6" @@ -68,7 +68,7 @@ follows="left|top" height="10" layout="topleft" - left_pad="15" + left_pad="13" name="glow label" text_readonly_color="LabelDisabledColor" top="6" @@ -84,7 +84,7 @@ left_delta="0" name="glow" top_pad="4" - width="80" /> + width="50" /> + + + - + Date: Tue, 15 Oct 2019 19:20:36 +0300 Subject: Buildfix (typo) --- indra/newview/llpanelface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 1e0b1874f7..fb99ffef09 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -307,7 +307,7 @@ BOOL LLPanelFace::postBuild() mBtnCopyFaces = getChild("copy_face_btn"); if(mBtnCopyFaces) { - BtnCopyFaces->setCommitCallback(boost::bind(&LLPanelFace::onCopyFaces, this)); + mBtnCopyFaces->setCommitCallback(boost::bind(&LLPanelFace::onCopyFaces, this)); } mBtnPasteFaces = getChild("paste_face_btn"); if (mBtnPasteFaces) -- cgit v1.2.3 From a09f68a809d8537041ea91c0768ba503f107f26b Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Thu, 17 Oct 2019 02:46:09 +0300 Subject: Buildfix (typo) --- indra/newview/llpanelface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index fb99ffef09..8f8f1b4763 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3161,7 +3161,7 @@ void LLPanelFace::pasteFace(LLViewerObject* objectp, S32 te) LLColor4 spec_color(te_data["material"]["SpecColor"]); LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); - LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te), object_id; + LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id); LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); if (te_data.has("shiny")) { -- cgit v1.2.3 From d3178573bb57a7c5cc997bde90a62e8d6a1affa4 Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Fri, 18 Oct 2019 17:23:28 +0300 Subject: SL-12156 FIXED [Project Copy/Paste] The prim's shape can be changed by pasting mesh parameters --- indra/newview/llpanelobject.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index a382813de6..56aea7db5e 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2158,7 +2158,10 @@ void LLPanelObject::onCopyParams() mParamsClipboard["is_physical"] = objectp->flagUsePhysics(); // Parametrics - getVolumeParams(mClipboardVolumeParams); + if (!objectp->isMesh()) + { + getVolumeParams(mClipboardVolumeParams); + } LLVOVolume *volobjp = NULL; if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) @@ -2188,19 +2191,22 @@ void LLPanelObject::onCopyParams() if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) { LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (canCopyTexture(texture_id)) - { - LL_INFOS() << "copu texture " << LL_ENDL; - mParamsClipboard["sculpt"]["id"] = texture_id; - } - else + + if (!objectp->isMesh()) { - mParamsClipboard["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); - } + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (canCopyTexture(texture_id)) + { + LL_INFOS() << "copy texture " << LL_ENDL; + mParamsClipboard["sculpt"]["id"] = texture_id; + } + else + { + mParamsClipboard["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); + } - mParamsClipboard["sculpt"]["type"] = sculpt_params->getSculptType(); + mParamsClipboard["sculpt"]["type"] = sculpt_params->getSculptType(); + } } // Light Source -- cgit v1.2.3 From 5310f215323aee7caec188ccc9d871e920385113 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 21 Oct 2019 17:46:26 +0300 Subject: SL-12158 Fixed messy 'Align' button positioning --- indra/newview/skins/default/xui/en/panel_tools_texture.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index ec610758cc..1819106970 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -806,14 +806,14 @@ top_delta="16" width="260" /> - - @@ -1858,7 +1722,7 @@ Paste Rotation increment="5" initial_value="0" layout="topleft" - left="135" + left="125" max_val="95" name="Scale 1" top_pad="4" @@ -1882,7 +1746,7 @@ Paste Rotation follows="left|top" height="15" layout="topleft" - left="135" + left="125" name="Hollow Shape" top_pad="4" width="150"> @@ -1960,7 +1824,7 @@ Paste Rotation follows="left|top" height="10" layout="topleft" - left="135" + left="125" name="scale_taper" top_pad="3" width="150"> @@ -2013,7 +1877,7 @@ Paste Rotation follows="left|top" height="10" layout="topleft" - left="135" + left="125" name="text topshear" top_pad="3" width="141"> @@ -2056,7 +1920,7 @@ Paste Rotation follows="left|top" height="10" layout="topleft" - left="135" + left="125" name="advanced_cut" top_pad="3" width="150"> @@ -2120,7 +1984,7 @@ Paste Rotation follows="left|top" height="10" layout="topleft" - left="135" + left="125" name="text taper2" top_pad="3" width="150"> @@ -2163,7 +2027,7 @@ Paste Rotation follows="left|top" height="10" layout="topleft" - left="135" + left="125" name="text radius delta" top_pad="2" width="78"> @@ -2188,7 +2052,7 @@ Paste Rotation increment="0.05" initial_value="0" layout="topleft" - left="135" + left="125" min_val="-1" name="Radius Offset" top_pad="4" @@ -2213,7 +2077,7 @@ Paste Rotation height="141" label="Sculpt Texture" layout="topleft" - left="135" + left="125" name="sculpt texture control" tool_tip="Click to choose a picture" top="70" @@ -2671,7 +2535,7 @@ Paste Rotation top_pad="8" width="132" /> - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.3 From f363646eb71d58007fc4936a67ad9c7bde9b93ac Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 2 Jun 2020 21:53:28 +0300 Subject: SL-13359 #2 UI changes for panel object todo: new icons, separator and some repositioning --- indra/newview/llpanelobject.cpp | 82 +++++++++++++++++++--- indra/newview/llpanelobject.h | 7 ++ .../newview/skins/default/xui/en/floater_tools.xml | 64 ++++++++++++++--- .../skins/default/xui/en/menu_copy_paste_pos.xml | 21 ++++++ .../skins/default/xui/en/menu_copy_paste_rot.xml | 21 ++++++ .../skins/default/xui/en/menu_copy_paste_size.xml | 21 ++++++ 6 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_size.xml (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 5fd9655201..e6bbac8247 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -118,8 +118,9 @@ BOOL LLPanelObject::postBuild() // Phantom checkbox mCheckPhantom = getChild("Phantom Checkbox Ctrl"); childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this); - + // Position + mMenuPastePos = getChild("paste_pos_btn"); mLabelPosition = getChild("label position"); mCtrlPosX = getChild("Pos X"); childSetCommitCallback("Pos X",onCommitPosition,this); @@ -129,6 +130,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Pos Z",onCommitPosition,this); // Scale + mMenuPasteSize = getChild("paste_size_btn"); mLabelSize = getChild("label size"); mCtrlScaleX = getChild("Scale X"); childSetCommitCallback("Scale X",onCommitScale,this); @@ -142,6 +144,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Scale Z",onCommitScale,this); // Rotation + mMenuPasteRot = getChild("paste_rot_btn"); mLabelRotation = getChild("label rotation"); mCtrlRotX = getChild("Rot X"); childSetCommitCallback("Rot X",onCommitRotation,this); @@ -291,6 +294,8 @@ LLPanelObject::LLPanelObject() mHasRotClipboard(FALSE), mSizeChanged(FALSE) { + mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2)); } @@ -377,7 +382,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_POS); } - + mMenuPastePos->setEnabled(enable_move); mLabelPosition->setEnabled( enable_move ); mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); @@ -403,6 +408,7 @@ void LLPanelObject::getState( ) calcp->setVar(LLCalc::Z_SCALE, 0.f); } + mMenuPasteSize->setEnabled(enable_scale); mLabelSize->setEnabled( enable_scale ); mCtrlScaleX->setEnabled( enable_scale ); mCtrlScaleY->setEnabled( enable_scale ); @@ -434,6 +440,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_ROT); } + mMenuPasteRot->setEnabled(enable_rotate); mLabelRotation->setEnabled( enable_rotate ); mCtrlRotX->setEnabled( enable_rotate ); mCtrlRotY->setEnabled( enable_rotate ); @@ -1648,6 +1655,8 @@ void LLPanelObject::sendPosition(BOOL btn_down) LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); LLViewerRegion* regionp = mObject->getRegion(); + if (!regionp) return; + // Clamp the Z height const F32 height = newpos.mV[VZ]; const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); @@ -2005,6 +2014,57 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } +void LLPanelObject::menuDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste + if (command == "pos_paste") + { + onPastePos(); + } + else if (command == "size_paste") + { + onPasteSize(); + } + else if (command == "rot_paste") + { + onPasteRot(); + } + // copy + else if (command == "pos_copy") + { + onCopyPos(); + } + else if (command == "size_copy") + { + onCopySize(); + } + else if (command == "rot_copy") + { + onCopyRot(); + } +} + +bool LLPanelObject::menuEnableItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if (command == "pos_paste") + { + return mHasPosClipboard; + } + else if (command == "size_paste") + { + return mHasSizeClipboard; + } + else if (command == "rot_paste") + { + return mHasRotClipboard; + } + return false; +} + void LLPanelObject::onCopyPos() { mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); @@ -2037,14 +2097,20 @@ void LLPanelObject::onCopyRot() void LLPanelObject::onPastePos() { - if(!mHasPosClipboard) return; + if (!mHasPosClipboard) return; + if (mObject.isNull()) return; + + LLViewerRegion* regionp = mObject->getRegion(); + if (!regionp) return; + // Clamp pos on non-attachments, just keep the prims within the region if (!mObject->isAttachment()) { - mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, 256.f); - mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, 256.f); - //height will get properly clammed by sendPosition + F32 max_width = regionp->getWidth(); // meters + mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, max_width); + mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width); + //height will get properly clamped by sendPosition } mCtrlPosX->set( mClipboardPos.mV[VX] ); @@ -2056,7 +2122,7 @@ void LLPanelObject::onPastePos() void LLPanelObject::onPasteSize() { - if(!mHasSizeClipboard) return; + if (!mHasSizeClipboard) return; mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); @@ -2071,7 +2137,7 @@ void LLPanelObject::onPasteSize() void LLPanelObject::onPasteRot() { - if(!mHasRotClipboard) return; + if (!mHasRotClipboard) return; mCtrlRotX->set( mClipboardRot.mV[VX] ); mCtrlRotY->set( mClipboardRot.mV[VY] ); diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index e9b9254a78..e8f8d0eb9a 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLTextBox; class LLUICtrl; class LLButton; +class LLMenuButton; class LLViewerObject; class LLComboBox; class LLColorSwatchCtrl; @@ -81,6 +82,9 @@ public: BOOL onDropSculpt(LLInventoryItem* item); static void onCommitSculptType( LLUICtrl *ctrl, void* userdata); + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); + protected: void getState(); @@ -137,17 +141,20 @@ protected: LLTextBox* mLabelRevolutions; LLSpinCtrl* mSpinRevolutions; + LLMenuButton* mMenuPastePos; LLTextBox* mLabelPosition; LLSpinCtrl* mCtrlPosX; LLSpinCtrl* mCtrlPosY; LLSpinCtrl* mCtrlPosZ; + LLMenuButton* mMenuPasteSize; LLTextBox* mLabelSize; LLSpinCtrl* mCtrlScaleX; LLSpinCtrl* mCtrlScaleY; LLSpinCtrl* mCtrlScaleZ; BOOL mSizeChanged; + LLMenuButton* mMenuPasteRot; LLTextBox* mLabelRotation; LLSpinCtrl* mCtrlRotX; LLSpinCtrl* mCtrlRotY; diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 0abee2ff80..2397be6b61 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1430,6 +1430,18 @@ even though the user gets a free copy. tool_tip="Causes object to not collide with other objects or avatars" top_pad="0" width="123" /> + - Position (meters) + Position + - Size (meters) + Size + - Rotation (degrees) + Rotation + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml new file mode 100644 index 0000000000..dcfb3faeca --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml new file mode 100644 index 0000000000..58d71b12d5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + -- cgit v1.2.3 From 30f1038351734b946be9a6f910e4e0eca82be1d4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 3 Jun 2020 16:12:11 +0300 Subject: SL-13359 #3 UI changes for panel object --- indra/newview/llpanelobject.cpp | 12 +++--- indra/newview/llpanelobject.h | 6 +-- .../textures/icons/ClipboardSmallMenu_Disabled.png | Bin 0 -> 218 bytes .../textures/icons/ClipboardSmallMenu_Off.png | Bin 0 -> 217 bytes .../textures/icons/ClipboardSmallMenu_Press.png | Bin 0 -> 215 bytes indra/newview/skins/default/textures/textures.xml | 4 ++ .../newview/skins/default/xui/en/floater_tools.xml | 48 +++++++++++++-------- 7 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png create mode 100644 indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png create mode 100644 indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index e6bbac8247..6fa2da7bac 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -120,7 +120,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this); // Position - mMenuPastePos = getChild("paste_pos_btn"); + mMenuClipboardPos = getChild("clipboard_pos_btn"); mLabelPosition = getChild("label position"); mCtrlPosX = getChild("Pos X"); childSetCommitCallback("Pos X",onCommitPosition,this); @@ -130,7 +130,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Pos Z",onCommitPosition,this); // Scale - mMenuPasteSize = getChild("paste_size_btn"); + mMenuClipboardSize = getChild("clipboard_size_btn"); mLabelSize = getChild("label size"); mCtrlScaleX = getChild("Scale X"); childSetCommitCallback("Scale X",onCommitScale,this); @@ -144,7 +144,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Scale Z",onCommitScale,this); // Rotation - mMenuPasteRot = getChild("paste_rot_btn"); + mMenuClipboardRot = getChild("clipboard_rot_btn"); mLabelRotation = getChild("label rotation"); mCtrlRotX = getChild("Rot X"); childSetCommitCallback("Rot X",onCommitRotation,this); @@ -382,7 +382,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_POS); } - mMenuPastePos->setEnabled(enable_move); + mMenuClipboardPos->setEnabled(enable_move); mLabelPosition->setEnabled( enable_move ); mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); @@ -408,7 +408,7 @@ void LLPanelObject::getState( ) calcp->setVar(LLCalc::Z_SCALE, 0.f); } - mMenuPasteSize->setEnabled(enable_scale); + mMenuClipboardSize->setEnabled(enable_scale); mLabelSize->setEnabled( enable_scale ); mCtrlScaleX->setEnabled( enable_scale ); mCtrlScaleY->setEnabled( enable_scale ); @@ -440,7 +440,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_ROT); } - mMenuPasteRot->setEnabled(enable_rotate); + mMenuClipboardRot->setEnabled(enable_rotate); mLabelRotation->setEnabled( enable_rotate ); mCtrlRotX->setEnabled( enable_rotate ); mCtrlRotY->setEnabled( enable_rotate ); diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index e8f8d0eb9a..764c0d8af4 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -141,20 +141,20 @@ protected: LLTextBox* mLabelRevolutions; LLSpinCtrl* mSpinRevolutions; - LLMenuButton* mMenuPastePos; + LLMenuButton* mMenuClipboardPos; LLTextBox* mLabelPosition; LLSpinCtrl* mCtrlPosX; LLSpinCtrl* mCtrlPosY; LLSpinCtrl* mCtrlPosZ; - LLMenuButton* mMenuPasteSize; + LLMenuButton* mMenuClipboardSize; LLTextBox* mLabelSize; LLSpinCtrl* mCtrlScaleX; LLSpinCtrl* mCtrlScaleY; LLSpinCtrl* mCtrlScaleZ; BOOL mSizeChanged; - LLMenuButton* mMenuPasteRot; + LLMenuButton* mMenuClipboardRot; LLTextBox* mLabelRotation; LLSpinCtrl* mCtrlRotX; LLSpinCtrl* mCtrlRotY; diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png new file mode 100644 index 0000000000..63b4bd2127 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png differ diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png new file mode 100644 index 0000000000..4200182b0c Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png differ diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png new file mode 100644 index 0000000000..e12887f489 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 7325d836d2..b7fa1e72f8 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -438,6 +438,10 @@ with the same filename but different name + + + + diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 2397be6b61..7768f894b8 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1430,19 +1430,29 @@ even though the user gets a free copy. tool_tip="Causes object to not collide with other objects or avatars" top_pad="0" width="123" /> + - Date: Wed, 3 Jun 2020 19:37:53 +0300 Subject: SL-13359 #4 Adjusted some elements --- indra/newview/skins/default/xui/en/floater_tools.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 7768f894b8..afc6155585 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1460,10 +1460,10 @@ even though the user gets a free copy. layout="topleft" name="label position" tool_tip="Position (meters)" - left_pad="3" + left_pad="8" top_delta="0" width="121"> - Position + Position (m) - Size + Size (m) - Rotation + Rotation (°) Date: Wed, 17 Jun 2020 23:38:55 +0300 Subject: SL-13359 #5 Implemented revised changes --- indra/newview/llfloatermodelpreview.cpp | 1 + indra/newview/llpanelface.cpp | 64 +----- indra/newview/llpanelface.h | 7 - indra/newview/llpanelobject.cpp | 219 ++++++++++++++++++--- indra/newview/llpanelobject.h | 11 +- indra/newview/lltexturectrl.cpp | 55 ++++++ indra/newview/lltexturectrl.h | 10 + .../textures/icons/ClipboardMenu_Disabled.png | Bin 0 -> 231 bytes .../default/textures/icons/ClipboardMenu_Off.png | Bin 0 -> 231 bytes .../default/textures/icons/ClipboardMenu_Press.png | Bin 0 -> 224 bytes indra/newview/skins/default/textures/textures.xml | 3 + .../newview/skins/default/xui/en/floater_tools.xml | 31 ++- .../default/xui/en/menu_copy_paste_generic.xml | 21 ++ .../skins/default/xui/en/menu_copy_paste_pos.xml | 26 ++- .../skins/default/xui/en/menu_copy_paste_rot.xml | 26 ++- .../skins/default/xui/en/menu_copy_paste_size.xml | 26 ++- 16 files changed, 382 insertions(+), 118 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png create mode 100644 indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png create mode 100644 indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml (limited to 'indra') diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index bc44e37c5a..f44dd92ddb 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4379,6 +4379,7 @@ void LLModelPreview::textureLoadedCallback( if(final && preview->mModelLoader) { + // for areTexturesReady() if(preview->mModelLoader->mNumOfFetchingTextures > 0) { preview->mModelLoader->mNumOfFetchingTextures-- ; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 369861fa25..6e99a10b98 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -54,7 +54,6 @@ #include "llmediaentry.h" #include "llmenubutton.h" #include "llnotificationsutil.h" -#include "llpanelobject.h" // LLPanelObject::canCopyTexture #include "llradiogroup.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -2929,7 +2928,7 @@ void LLPanelFace::onCopyFaces() { LLUUID item_id; LLUUID id = te_data["te"]["imageid"].asUUID(); - bool full_perm = LLPanelFace::isLibraryTexture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); + bool full_perm = get_is_library_texture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); if (id.notNull() && !full_perm) { @@ -2944,7 +2943,7 @@ void LLPanelFace::onCopyFaces() // as result it is Hightly unreliable, leaves little control to user, borderline hack // but there are little options to preserve permissions - multiple inventory // items might reference same asset and inventory search is expensive. - item_id = LLPanelFace::getCopyPermInventoryTextureId(id); + item_id = get_copy_free_item_by_asset_id(id); // record value to avoid repeating inventory search when possible asset_item_map[id] = item_id; } @@ -3022,7 +3021,7 @@ void LLPanelFace::onCopyFaces() if (mat_data.has("NormMap")) { LLUUID id = mat_data["NormMap"].asUUID(); - if (id.notNull() && !LLPanelFace::canCopyTexture(id)) + if (id.notNull() && !get_can_copy_texture(id)) { mat_data["NormMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); mat_data["NormMapNoCopy"] = true; @@ -3032,7 +3031,7 @@ void LLPanelFace::onCopyFaces() if (mat_data.has("SpecMap")) { LLUUID id = mat_data["SpecMap"].asUUID(); - if (id.notNull() && !LLPanelFace::canCopyTexture(id)) + if (id.notNull() && !get_can_copy_texture(id)) { mat_data["SpecMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); mat_data["SpecMapNoCopy"] = true; @@ -3504,58 +3503,3 @@ bool LLPanelFace::pasteEnabletMenuItem(const LLSD& userdata) return true; } - -//static -bool LLPanelFace::isLibraryTexture(LLUUID image_id) -{ - if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) - || image_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) - || image_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) - || image_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) - || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) - { - return true; - } - return false; -} - -//static -LLUUID LLPanelFace::getCopyPermInventoryTextureId(LLUUID image_id) -{ - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(image_id); - gInventory.collectDescendentsIf(LLUUID::null, - cats, - items, - LLInventoryModel::INCLUDE_TRASH, - asset_id_matches); - if (items.size()) - { - for (S32 i = 0; i < items.size(); i++) - { - LLViewerInventoryItem* itemp = items[i]; - if (itemp) - { - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowOperationBy(PERM_COPY, - gAgent.getID(), - gAgent.getGroupID())) - { - return itemp->getUUID(); - } - } - } - } - return LLUUID::null; -} - -// Static -bool LLPanelFace::canCopyTexture(LLUUID image_id) -{ - // User is allowed to copy a texture if: - // library asset or default texture, - // or copy perm asset exists in user's inventory - - return isLibraryTexture(image_id) || getCopyPermInventoryTextureId(image_id).notNull(); -} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index dbf3531332..770f10e2ee 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -115,13 +115,6 @@ public: LLRender::eTexIndex getTextureChannelToEdit(); void pasteFace(LLViewerObject* object, S32 te); - static bool isLibraryTexture(LLUUID image_id); - - // Finds copy-enabled texture with specified asset from inventory - // This can be performance unfriendly and doesn't warranty that - // the texture is original source of asset - static LLUUID getCopyPermInventoryTextureId(LLUUID image_id); - static bool canCopyTexture(LLUUID image_id); protected: void getState(); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 6fa2da7bac..f1426ddf33 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -159,6 +159,8 @@ BOOL LLPanelObject::postBuild() mComboBaseType = getChild("comboBaseType"); childSetCommitCallback("comboBaseType",onCommitParametric,this); + mMenuClipboardParams = getChild("clipboard_params_btn"); + // Cut mLabelCut = getChild("text cut"); mSpinCutBegin = getChild("cut begin"); @@ -289,9 +291,10 @@ LLPanelObject::LLPanelObject() mSelectedType(MI_BOX), mSculptTextureRevert(LLUUID::null), mSculptTypeRevert(0), - mHasPosClipboard(FALSE), - mHasSizeClipboard(FALSE), - mHasRotClipboard(FALSE), + mHasClipboardPos(false), + mHasClipboardSize(false), + mHasClipboardRot(false), + mHasClipboardParams(false), mSizeChanged(FALSE) { mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); @@ -618,7 +621,7 @@ void LLPanelObject::getState( ) } else { - LL_INFOS() << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; + LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; selected_item = MI_BOX; } @@ -944,6 +947,7 @@ void LLPanelObject::getState( ) // Update field enablement mComboBaseType ->setEnabled( enabled ); + mMenuClipboardParams->setEnabled(enabled); mLabelCut ->setEnabled( enabled ); mSpinCutBegin ->setEnabled( enabled ); @@ -1104,7 +1108,8 @@ void LLPanelObject::getState( ) } mComboBaseType->setEnabled(!isMesh); - + mMenuClipboardParams->setEnabled(!isMesh); + if (mCtrlSculptType) { if (sculpt_stitching == LL_SCULPT_TYPE_NONE) @@ -1168,11 +1173,11 @@ void LLPanelObject::sendIsPhysical() LLSelectMgr::getInstance()->selectionUpdatePhysics(value); mIsPhysical = value; - LL_INFOS() << "update physics sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL; } else { - LL_INFOS() << "update physics not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL; } } @@ -1184,11 +1189,11 @@ void LLPanelObject::sendIsTemporary() LLSelectMgr::getInstance()->selectionUpdateTemporary(value); mIsTemporary = value; - LL_INFOS() << "update temporary sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL; } else { - LL_INFOS() << "update temporary not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL; } } @@ -1201,11 +1206,11 @@ void LLPanelObject::sendIsPhantom() LLSelectMgr::getInstance()->selectionUpdatePhantom(value); mIsPhantom = value; - LL_INFOS() << "update phantom sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL; } else { - LL_INFOS() << "update phantom not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL; } } @@ -1315,7 +1320,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) break; default: - LL_WARNS() << "Unknown base type " << selected_type + LL_WARNS("FloaterTools") << "Unknown base type " << selected_type << " in getVolumeParams()" << LL_ENDL; // assume a box selected_type = MI_BOX; @@ -2019,7 +2024,13 @@ void LLPanelObject::menuDoToSelected(const LLSD& userdata) std::string command = userdata.asString(); // paste - if (command == "pos_paste") + if (command == "psr_paste") + { + onPastePos(); + onPasteSize(); + onPasteRot(); + } + else if (command == "pos_paste") { onPastePos(); } @@ -2031,7 +2042,17 @@ void LLPanelObject::menuDoToSelected(const LLSD& userdata) { onPasteRot(); } + else if (command == "params_paste") + { + onPasteParams(); + } // copy + else if (command == "psr_copy") + { + onCopyPos(); + onCopySize(); + onCopyRot(); + } else if (command == "pos_copy") { onCopyPos(); @@ -2044,23 +2065,71 @@ void LLPanelObject::menuDoToSelected(const LLSD& userdata) { onCopyRot(); } + else if (command == "params_copy") + { + onCopyParams(); + } } bool LLPanelObject::menuEnableItem(const LLSD& userdata) { std::string command = userdata.asString(); - if (command == "pos_paste") + // paste options + if (command == "psr_paste") + { + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) + && (selected_count == 1); + + if (!single_volume) + { + return false; + } + + bool enable_move; + bool enable_modify; + + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + + return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot; + } + else if (command == "pos_paste") { - return mHasPosClipboard; + // assumes that menu won't be active if there is no move permission + return mHasClipboardPos; } else if (command == "size_paste") { - return mHasSizeClipboard; + return mHasClipboardSize; } else if (command == "rot_paste") { - return mHasRotClipboard; + return mHasClipboardRot; + } + else if (command == "params_paste") + { + return mHasClipboardParams; + } + // copy options + else if (command == "psr_copy") + { + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) + && (selected_count == 1); + + if (!single_volume) + { + return false; + } + + bool enable_move; + bool enable_modify; + + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + + // since we forbid seeing values we also should forbid copying them + return enable_move && enable_modify; } return false; } @@ -2072,7 +2141,7 @@ void LLPanelObject::onCopyPos() std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]); LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - mHasPosClipboard = TRUE; + mHasClipboardPos = true; } void LLPanelObject::onCopySize() @@ -2082,7 +2151,7 @@ void LLPanelObject::onCopySize() std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]); LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - mHasSizeClipboard = TRUE; + mHasClipboardSize = true; } void LLPanelObject::onCopyRot() @@ -2092,12 +2161,12 @@ void LLPanelObject::onCopyRot() std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]); LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - mHasRotClipboard = TRUE; + mHasClipboardRot = true; } void LLPanelObject::onPastePos() { - if (!mHasPosClipboard) return; + if (!mHasClipboardPos) return; if (mObject.isNull()) return; LLViewerRegion* regionp = mObject->getRegion(); @@ -2122,26 +2191,118 @@ void LLPanelObject::onPastePos() void LLPanelObject::onPasteSize() { - if (!mHasSizeClipboard) return; + if (!mHasClipboardSize) return; mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); - mCtrlScaleX->set( mClipboardSize.mV[VX] ); - mCtrlScaleY->set( mClipboardSize.mV[VY] ); - mCtrlScaleZ->set( mClipboardSize.mV[VZ] ); + mCtrlScaleX->set(mClipboardSize.mV[VX]); + mCtrlScaleY->set(mClipboardSize.mV[VY]); + mCtrlScaleZ->set(mClipboardSize.mV[VZ]); sendScale(FALSE); } void LLPanelObject::onPasteRot() { - if (!mHasRotClipboard) return; + if (!mHasClipboardRot) return; - mCtrlRotX->set( mClipboardRot.mV[VX] ); - mCtrlRotY->set( mClipboardRot.mV[VY] ); - mCtrlRotZ->set( mClipboardRot.mV[VZ] ); + mCtrlRotX->set(mClipboardRot.mV[VX]); + mCtrlRotY->set(mClipboardRot.mV[VY]); + mCtrlRotZ->set(mClipboardRot.mV[VZ]); sendRotation(FALSE); } + +void LLPanelObject::onCopyParams() +{ + LLViewerObject* objectp = mObject; + if (!objectp) + { + return; + } + + mClipboardParams.clear(); + + // Parametrics + if (!objectp->isMesh()) + { + LLVolumeParams params; + getVolumeParams(params); + mClipboardParams["volume_params"] = params.asLLSD(); + } + + // Sculpted Prim + if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + + if (!objectp->isMesh()) + { + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) + { + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; + } + else + { + mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); + } + + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + } + } + + mHasClipboardParams = TRUE; +} + +void LLPanelObject::onPasteParams() +{ + LLViewerObject* objectp = mObject; + if (!objectp || !mHasClipboardParams) + { + return; + } + + // Sculpted Prim + if (mClipboardParams.has("sculpt")) + { + LLSculptParams sculpt_params; + LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID(); + U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger(); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); + objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); + } + else + { + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if (sculpt_params) + { + objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); + } + } + + // volume params + // make sure updateVolume() won't affect flexible + if (mClipboardParams.has("volume_params")) + { + LLVolumeParams params; + params.fromLLSD(mClipboardParams["volume_params"]); + LLVOVolume *volobjp = (LLVOVolume *)objectp; + if (volobjp->isFlexible()) + { + if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE) + { + params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE); + } + } + else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) + { + params.getPathParams().setCurveType(LL_PCODE_PATH_LINE); + } + + objectp->updateVolume(params); + } +} diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 764c0d8af4..5ea3d07699 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -73,6 +73,8 @@ public: void onPasteSize(); void onCopyRot(); void onPasteRot(); + void onCopyParams(); + void onPasteParams(); static void onCommitParametric(LLUICtrl* ctrl, void* userdata); @@ -102,6 +104,7 @@ protected: protected: // Per-object options LLComboBox* mComboBaseType; + LLMenuButton* mMenuClipboardParams; LLTextBox* mLabelCut; LLSpinCtrl* mSpinCutBegin; @@ -183,10 +186,12 @@ protected: LLVector3 mClipboardPos; LLVector3 mClipboardSize; LLVector3 mClipboardRot; + LLSD mClipboardParams; - BOOL mHasPosClipboard; - BOOL mHasSizeClipboard; - BOOL mHasRotClipboard; + bool mHasClipboardPos; + bool mHasClipboardSize; + bool mHasClipboardRot; + bool mHasClipboardParams; LLPointer mObject; LLPointer mRootObject; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 6a0464c657..2f5be2b32e 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -79,6 +79,61 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1; //static const char WHITE_IMAGE_NAME[] = "Blank Texture"; //static const char NO_IMAGE_NAME[] = "None"; + + +//static +bool get_is_library_texture(LLUUID image_id) +{ + if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) + || image_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) + || image_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) + || image_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) + || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) + { + return true; + } + return false; +} + +LLUUID get_copy_free_item_by_asset_id(LLUUID image_id) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(image_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + if (items.size()) + { + for (S32 i = 0; i < items.size(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp) + { + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + return itemp->getUUID(); + } + } + } + } + return LLUUID::null; +} + +bool get_can_copy_texture(LLUUID image_id) +{ + // User is allowed to copy a texture if: + // library asset or default texture, + // or copy perm asset exists in user's inventory + + return get_is_library_texture(image_id) || get_copy_free_item_by_asset_id(image_id).notNull(); +} + LLFloaterTexturePicker::LLFloaterTexturePicker( LLView* owner, LLUUID image_asset_id, diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index b2a34a37c4..2b2c5fa237 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -53,6 +53,16 @@ class LLViewerFetchedTexture; typedef boost::function drag_n_drop_callback; typedef boost::function texture_selected_callback; +// Helper functions for UI that work with picker +bool get_is_library_texture(LLUUID image_id); + +// texture picker works by asset ids since objects normaly do +// not retain inventory ids as result these functions are looking +// for textures in inventory by asset ids +// This search can be performance unfriendly and doesn't warranty +// that the texture is original source of asset +LLUUID get_copy_free_item_by_asset_id(LLUUID image_id); +bool get_can_copy_texture(LLUUID image_id); ////////////////////////////////////////////////////////////////////////////////////////// // LLTextureCtrl diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png new file mode 100644 index 0000000000..9a81c5f94b Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png differ diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png new file mode 100644 index 0000000000..88012cf8d1 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png differ diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png new file mode 100644 index 0000000000..ab02e7d42d Binary files /dev/null and b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b7fa1e72f8..473b074213 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -441,6 +441,9 @@ with the same filename but different name + + + diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index afc6155585..0b2b1abeb9 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1436,7 +1436,7 @@ even though the user gets a free copy. height="0" layout="topleft" left_delta="0" - name="lod_tab_border" + name="object_horizontal" top_pad="10" width="95" /> Prim Type --> + + + width="125"> + Path Cut (begin/end) diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml new file mode 100644 index 0000000000..8e016e4a1c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml index c2763af603..3ea95b281f 100644 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml @@ -3,19 +3,35 @@ layout="topleft" name="Copy Paste Position Menu"> + + + + - + + + + + - - + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml index dcfb3faeca..06ce80f897 100644 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml @@ -3,19 +3,35 @@ layout="topleft" name="Copy Paste Rotation Menu"> + + + + - + + + + + - - + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml index 58d71b12d5..7082a0e65b 100644 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml @@ -3,19 +3,35 @@ layout="topleft" name="Copy Paste Size Menu"> + + + + - + + + + + - - + + -- cgit v1.2.3 From ef8d42a05ecd611c2bd16492c6727813bdcfd6bb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 18 Jun 2020 00:13:38 +0300 Subject: SL-13359 #6 Fixed padding --- .../newview/skins/default/xui/en/floater_tools.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 0b2b1abeb9..d93ce2af1c 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1737,7 +1737,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text cut" - top_pad="7" + top_pad="5" width="150"> Path Cut (begin/end) @@ -1775,7 +1775,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text hollow" - top_pad="6" + top_pad="7" width="68"> Hollow @@ -1823,7 +1823,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="Hollow Shape" - top_pad="4" + top_pad="7" width="150"> Hollow Shape @@ -1859,7 +1859,7 @@ even though the user gets a free copy. layout="topleft" left_delta="0" name="text twist" - top_pad="5" + top_pad="7" width="150"> Twist (begin/end) @@ -1901,12 +1901,12 @@ even though the user gets a free copy. layout="topleft" left="125" name="scale_taper" - top_pad="3" + top_pad="7" width="150"> Taper Top Shear @@ -1997,12 +1997,12 @@ even though the user gets a free copy. layout="topleft" left="125" name="advanced_cut" - top_pad="3" + top_pad="7" width="150"> Profile Cut (begin/end) Taper @@ -2104,7 +2104,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text radius delta" - top_pad="2" + top_pad="7" width="78"> Radius -- cgit v1.2.3 From d95f86c5931db5b025e0923071c9b3a08bb25301 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 18 Jun 2020 22:38:58 +0300 Subject: SL-13359 #7 Features tab --- indra/newview/llpanelobject.cpp | 43 ++- indra/newview/llpanelobject.h | 1 - indra/newview/llpanelvolume.cpp | 297 ++++++++++++++++++++- indra/newview/llpanelvolume.h | 13 + .../newview/skins/default/xui/en/floater_tools.xml | 43 ++- .../default/xui/en/menu_copy_paste_features.xml | 21 ++ .../default/xui/en/menu_copy_paste_generic.xml | 21 -- .../skins/default/xui/en/menu_copy_paste_light.xml | 21 ++ .../default/xui/en/menu_copy_paste_object.xml | 21 ++ 9 files changed, 428 insertions(+), 53 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_features.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_light.xml create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_object.xml (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index f1426ddf33..9bdc68b86a 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -159,7 +159,7 @@ BOOL LLPanelObject::postBuild() mComboBaseType = getChild("comboBaseType"); childSetCommitCallback("comboBaseType",onCommitParametric,this); - mMenuClipboardParams = getChild("clipboard_params_btn"); + mMenuClipboardParams = getChild("clipboard_obj_params_btn"); // Cut mLabelCut = getChild("text cut"); @@ -294,7 +294,6 @@ LLPanelObject::LLPanelObject() mHasClipboardPos(false), mHasClipboardSize(false), mHasClipboardRot(false), - mHasClipboardParams(false), mSizeChanged(FALSE) { mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); @@ -2109,7 +2108,7 @@ bool LLPanelObject::menuEnableItem(const LLSD& userdata) } else if (command == "params_paste") { - return mHasClipboardParams; + return mClipboardParams.isMap() && !mClipboardParams.emptyMap(); } // copy options else if (command == "psr_copy") @@ -2218,7 +2217,7 @@ void LLPanelObject::onPasteRot() void LLPanelObject::onCopyParams() { LLViewerObject* objectp = mObject; - if (!objectp) + if (!objectp || objectp->isMesh()) { return; } @@ -2226,42 +2225,34 @@ void LLPanelObject::onCopyParams() mClipboardParams.clear(); // Parametrics - if (!objectp->isMesh()) - { - LLVolumeParams params; - getVolumeParams(params); - mClipboardParams["volume_params"] = params.asLLSD(); - } + LLVolumeParams params; + getVolumeParams(params); + mClipboardParams["volume_params"] = params.asLLSD(); // Sculpted Prim if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) { LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (!objectp->isMesh()) + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) { - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (get_can_copy_texture(texture_id)) - { - LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; - mClipboardParams["sculpt"]["id"] = texture_id; - } - else - { - mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); - } - - mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; + } + else + { + mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); } - } - mHasClipboardParams = TRUE; + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + } } void LLPanelObject::onPasteParams() { LLViewerObject* objectp = mObject; - if (!objectp || !mHasClipboardParams) + if (!objectp) { return; } diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 5ea3d07699..515dd27c0a 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -191,7 +191,6 @@ protected: bool mHasClipboardPos; bool mHasClipboardSize; bool mHasClipboardRot; - bool mHasClipboardParams; LLPointer mObject; LLPointer mRootObject; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 05d9346f89..a03e85daff 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -50,6 +50,7 @@ //#include "llfirstuse.h" #include "llfocusmgr.h" #include "llmanipscale.h" +#include "llmenubutton.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -166,6 +167,9 @@ BOOL LLPanelVolume::postBuild() mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution)); } + mMenuClipboardFeatures = getChild("clipboard_features_params_btn"); + mMenuClipboardLight = getChild("clipboard_light_params_btn"); + std::map material_name_map; material_name_map["Stone"]= LLTrans::getString("Stone"); material_name_map["Metal"]= LLTrans::getString("Metal"); @@ -206,6 +210,8 @@ LLPanelVolume::LLPanelVolume() { setMouseOpaque(FALSE); + mCommitCallbackRegistrar.add("PanelVolume.menuDoToSelected", boost::bind(&LLPanelVolume::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelVolume.menuEnable", boost::bind(&LLPanelVolume::menuEnableItem, this, _2)); } @@ -407,7 +413,6 @@ void LLPanelVolume::getState( ) gAgentAvatarp->updateMeshVisibility(); } } - // Flexible properties BOOL is_flexible = volobjp && volobjp->isFlexible(); @@ -562,6 +567,9 @@ void LLPanelVolume::getState( ) 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 @@ -662,6 +670,9 @@ void LLPanelVolume::clearCtrls() mSpinPhysicsRestitution->setEnabled(FALSE); mComboMaterial->setEnabled( FALSE ); + + mMenuClipboardFeatures->setEnabled(false); + mMenuClipboardLight->setEnabled(false); } // @@ -829,6 +840,290 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data) } } +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 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(is_flexible)) + { + 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]; + } + } + } + + 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); + } + } +} + +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 ) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 66117316cf..1651108093 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLTextBox; class LLUICtrl; class LLButton; +class LLMenuButton; class LLViewerObject; class LLComboBox; class LLColorSwatchCtrl; @@ -73,6 +74,13 @@ public: void onLightCancelTexture(const LLSD& data); void onLightSelectTexture(const LLSD& data); + void onCopyFeatures(); + void onPasteFeatures(); + void onCopyLight(); + void onPasteLight(); + + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); protected: void getState(); @@ -120,6 +128,11 @@ protected: LLSpinCtrl* mSpinPhysicsFriction; LLSpinCtrl* mSpinPhysicsDensity; LLSpinCtrl* mSpinPhysicsRestitution; + + LLMenuButton* mMenuClipboardFeatures; + LLMenuButton* mMenuClipboardLight; + + LLSD mClipboardParams; }; #endif diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index d93ce2af1c..6e08be4866 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1717,7 +1717,7 @@ even though the user gets a free copy. value="Sculpted" /> None Prim Convex Hull + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml deleted file mode 100644 index 8e016e4a1c..0000000000 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_generic.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml new file mode 100644 index 0000000000..941efe7d01 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml new file mode 100644 index 0000000000..8e016e4a1c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + -- cgit v1.2.3 From 15f02e2da231827a7cac18a2444c212efc8c1d1c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 19 Jun 2020 17:34:57 +0300 Subject: SL-13359 #8 Reverted changes to texture tab This reverts commit 1e1707d532560583744bb877adfed11864f2db31. --- indra/newview/llpanelface.cpp | 659 +-------------------- indra/newview/llpanelface.h | 29 +- .../skins/default/xui/en/menu_texture_paste.xml | 70 --- .../skins/default/xui/en/panel_tools_texture.xml | 55 +- 4 files changed, 16 insertions(+), 797 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/menu_texture_paste.xml (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 6e99a10b98..778cb77309 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,7 +38,6 @@ #include "llfontgl.h" // project includes -#include "llagent.h" // gAgent #include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -46,13 +45,9 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" -#include "llinventoryfunctions.h" -#include "llinventorymodel.h" // gInventory -#include "llinventorymodelbackgroundfetch.h" #include "lllineeditor.h" #include "llmaterialmgr.h" #include "llmediaentry.h" -#include "llmenubutton.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "llresmgr.h" @@ -305,18 +300,7 @@ BOOL LLPanelFace::postBuild() { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - - mBtnCopyFaces = getChild("copy_face_btn"); - if(mBtnCopyFaces) - { - mBtnCopyFaces->setCommitCallback(boost::bind(&LLPanelFace::onCopyFaces, this)); - } - mBtnPasteFaces = getChild("paste_face_btn"); - if (mBtnPasteFaces) - { - mBtnPasteFaces->setCommitCallback(boost::bind(&LLPanelFace::onPasteFaces, this)); - } - mBtnPasteMenu = getChild("paste_face_gear_btn"); + clearCtrls(); @@ -325,22 +309,9 @@ BOOL LLPanelFace::postBuild() LLPanelFace::LLPanelFace() : LLPanel(), - mIsAlpha(false), - mPasteColor(TRUE), - mPasteAlpha(TRUE), - mPasteGlow(TRUE), - mPasteDiffuse(TRUE), - mPasteNormal(TRUE), - mPasteSpecular(TRUE), - mPasteMapping(TRUE), - mPasteMedia(TRUE), - mPopulateAllTEs(TRUE) + mIsAlpha(false) { USE_TEXTURE = LLTrans::getString("use_texture"); - - mEnableCallbackRegistrar.add("BuildFace.PasteCheckItem", boost::bind(&LLPanelFace::pasteCheckMenuItem, this, _2)); - mCommitCallbackRegistrar.add("BuildFace.PasteDoToSelected", boost::bind(&LLPanelFace::pasteDoMenuItem, this, _2)); - mEnableCallbackRegistrar.add("BuildFace.PasteEnable", boost::bind(&LLPanelFace::pasteEnabletMenuItem, this, _2)); } @@ -1566,12 +1537,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - BOOL single_volume = (selected_count == 1); - mBtnCopyFaces->setEnabled(editable && single_volume); - mBtnPasteFaces->setEnabled(editable && (mClipboard.size() > 0)); - mBtnPasteMenu->setEnabled(editable); - // Set variable values for numeric expressions LLCalc* calcp = LLCalc::getInstance(); calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal()); @@ -1772,6 +1737,8 @@ void LLPanelFace::updateVisibility() getChildView("bumpyRot")->setVisible(show_bumpiness); getChildView("bumpyOffsetU")->setVisible(show_bumpiness); getChildView("bumpyOffsetV")->setVisible(show_bumpiness); + + } // static @@ -2885,621 +2852,3 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic } max_diff_repeats_func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats ); } - -static LLSD texture_clipboard; - -void LLPanelFace::onCopyFaces() -{ - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - if( !objectp || !node - || objectp->getPCode() != LL_PCODE_VOLUME - || !objectp->permModify() - || objectp->isPermanentEnforced() - || selected_count > 1) - { - return; - } - - mClipboard.clear(); - std::map asset_item_map; - - S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); - mPopulateAllTEs = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); - for (S32 te = 0; te < num_tes; ++te) - { - if (node->isTESelected(te)) - { - LLTextureEntry* tep = objectp->getTE(te); - if (tep) - { - LLSD te_data; - - // asLLSD() includes media - te_data["te"] = tep->asLLSD(); - te_data["te"]["glow"] = tep->getGlow(); - te_data["te"]["shiny"] = tep->getShiny(); - te_data["te"]["bumpmap"] = tep->getBumpmap(); - te_data["te"]["bumpshiny"] = tep->getBumpShiny(); - te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright(); - - if (te_data["te"].has("imageid")) - { - LLUUID item_id; - LLUUID id = te_data["te"]["imageid"].asUUID(); - bool full_perm = get_is_library_texture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); - - if (id.notNull() && !full_perm) - { - std::map::iterator iter = asset_item_map.find(id); - if (iter != asset_item_map.end()) - { - item_id = iter->second; - } - else - { - // What this does is simply searches inventory for item with same asset id, - // as result it is Hightly unreliable, leaves little control to user, borderline hack - // but there are little options to preserve permissions - multiple inventory - // items might reference same asset and inventory search is expensive. - item_id = get_copy_free_item_by_asset_id(id); - // record value to avoid repeating inventory search when possible - asset_item_map[id] = item_id; - } - } - - if (id.isNull() - || (!full_perm && item_id.isNull())) - { - if (!LLLocalBitmapMgr::getInstance()->isLocal(id)) - { - te_data["te"].erase("imageid"); - te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); - } - te_data["te"]["itemfullperm"] = true; - } - else - { - te_data["te"]["itemfullperm"] = full_perm; - // If full permission object, texture is free to copy, - // but otherwise we need to check inventory and extract permissions - // - // Normally we care only about restrictions for current user and objects - // don't inherit any 'next owner' permissions from texture, so there is - // no need to record item id if full_perm==true - if (!full_perm && item_id.notNull()) - { - LLViewerInventoryItem* itemp = gInventory.getItem(item_id); - if (itemp) - { - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowOperationBy(PERM_COPY, - gAgent.getID(), - gAgent.getGroupID())) - { - te_data["te"]["imageitemid"] = item_id; - te_data["te"]["itemfullperm"] = itemp->getIsFullPerm(); - if (!itemp->isFinished()) - { - // needed for dropTextureAllFaces - LLInventoryModelBackgroundFetch::instance().start(item_id, false); - } - } - } - } - } - } - - LLMaterialPtr material_ptr = tep->getMaterialParams(); - if (!material_ptr.isNull()) - { - LLSD mat_data; - - mat_data["NormMap"] = material_ptr->getNormalID(); - mat_data["SpecMap"] = material_ptr->getSpecularID(); - - mat_data["NormRepX"] = material_ptr->getNormalRepeatX(); - mat_data["NormRepY"] = material_ptr->getNormalRepeatY(); - mat_data["NormOffX"] = material_ptr->getNormalOffsetX(); - mat_data["NormOffY"] = material_ptr->getNormalOffsetY(); - mat_data["NormRot"] = material_ptr->getNormalRotation(); - - mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX(); - mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY(); - mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX(); - mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY(); - mat_data["SpecRot"] = material_ptr->getSpecularRotation(); - - mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue(); - mat_data["SpecExp"] = material_ptr->getSpecularLightExponent(); - mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity(); - mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff(); - mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode(); - - // Replace no-copy textures, destination texture will get used instead if available - if (mat_data.has("NormMap")) - { - LLUUID id = mat_data["NormMap"].asUUID(); - if (id.notNull() && !get_can_copy_texture(id)) - { - mat_data["NormMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); - mat_data["NormMapNoCopy"] = true; - } - - } - if (mat_data.has("SpecMap")) - { - LLUUID id = mat_data["SpecMap"].asUUID(); - if (id.notNull() && !get_can_copy_texture(id)) - { - mat_data["SpecMap"] = LLUUID(gSavedSettings.getString( "DefaultObjectTexture" )); - mat_data["SpecMapNoCopy"] = true; - } - - } - - te_data["material"] = mat_data; - } - - mClipboard.append(te_data); - } - } - } -} - -void LLPanelFace::pasteFace(LLViewerObject* objectp, S32 te) -{ - LLSD te_data; - if ((mClipboard.size() == 1) && mPopulateAllTEs) - { - te_data = *(mClipboard.beginArray()); - } - else if (mClipboard[te]) - { - te_data = mClipboard[te]; - } - else - { - return; - } - - LLTextureEntry* tep = objectp->getTE(te); - if (tep) - { - if (te_data.has("te")) - { - // Texture - bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); - if (mPasteDiffuse && te_data["te"].has("imageid")) - { - const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id - LLViewerInventoryItem* itemp_res = NULL; - - if (te_data["te"].has("imageitemid")) - { - LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); - if (item_id.notNull()) - { - LLViewerInventoryItem* itemp = gInventory.getItem(item_id); - if (itemp && itemp->isFinished()) - { - // dropTextureAllFaces will fail if incomplete - itemp_res = itemp; - } - } - } - - // for case when item got removed from inventory after we pressed 'copy' - if (!itemp_res && !full_perm) - { - // todo: fix this, we are often searching same tuxter multiple times (equal to number of faces) - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(imageid); - gInventory.collectDescendentsIf(LLUUID::null, - cats, - items, - LLInventoryModel::INCLUDE_TRASH, - asset_id_matches); - - // Extremely unreliable and perfomance unfriendly. - // But we need this to check permissions and it is how texture control finds items - for (S32 i = 0; i < items.size(); i++) - { - LLViewerInventoryItem* itemp = items[i]; - if (itemp && itemp->isFinished()) - { - // dropTextureAllFaces will fail if incomplete - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowOperationBy(PERM_COPY, - gAgent.getID(), - gAgent.getGroupID())) - { - itemp_res = itemp; - break; // first match - } - } - } - } - - if (itemp_res) - { - if (te == -1) // all faces - { - LLToolDragAndDrop::dropTextureAllFaces(objectp, - itemp_res, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } - else // one face - { - LLToolDragAndDrop::dropTextureOneFace(objectp, - te, - itemp_res, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } - } - // not an inventory item or no complete items - else if (full_perm) - { - // Either library, local or existed as fullperm when user made a copy - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - objectp->setTEImage(U8(te), image); - } - } - - // Color / Alpha - if ((mPasteColor || mPasteAlpha) && te_data["te"].has("colors")) - { - LLColor4 color = tep->getColor(); - - LLColor4 clip_color; - clip_color.setValue(te_data["te"]["colors"]); - - // Color - if (mPasteColor) - { - color.mV[VRED] = clip_color.mV[VRED]; - color.mV[VGREEN] = clip_color.mV[VGREEN]; - color.mV[VBLUE] = clip_color.mV[VBLUE]; - } - - // Alpha - if (mPasteAlpha) - { - color.mV[VALPHA] = clip_color.mV[VALPHA]; - } - - objectp->setTEColor(te, color); - } - - if (mPasteColor && te_data["te"].has("fullbright")) - { - objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger()); - } - - - // Glow - if (mPasteGlow && te_data["te"].has("glow")) - { - objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal()); - } - - if (mPasteNormal && te_data["te"].has("bumpmap")) - { - objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger()); - } - if (mPasteSpecular && te_data["te"].has("bumpshiny")) - { - objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger()); - } - if (mPasteSpecular && te_data["te"].has("bumpfullbright")) - { - objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger()); - } - - // Texture map - if (mPasteMapping) - { - if (te_data["te"].has("scales") && te_data["te"].has("scalet")) - { - objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal()); - } - if (te_data["te"].has("offsets") && te_data["te"].has("offsett")) - { - objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal()); - } - if (te_data["te"].has("imagerot")) - { - objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal()); - } - } - - // Media - if (mPasteMedia && te_data["te"].has("media_flags")) - { - U8 media_flags = te_data["te"]["media_flags"].asInteger(); - objectp->setTEMediaFlags(te, media_flags); - LLVOVolume *vo = dynamic_cast(objectp); - if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY)) - { - vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/); - } - } - else - { - // Keep media flags on destination unchanged - } - } - - if (te_data.has("material")) - { - LLUUID object_id = objectp->getID(); - - LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); - - if (mPasteNormal) - { - // Replace placeholders with target's - if (te_data["material"].has("NormMapNoCopy")) - { - LLMaterialPtr material = tep->getMaterialParams(); - if (material.notNull()) - { - LLUUID id = material->getNormalID(); - if (id.notNull()) - { - te_data["material"]["NormMap"] = id; - } - } - } - LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id); - LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id); - LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id); - LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id); - LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id); - LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id); - } - - if (mPasteSpecular) - { - // Replace placeholders with target's - if (te_data["material"].has("SpecMapNoCopy")) - { - LLMaterialPtr material = tep->getMaterialParams(); - if (material.notNull()) - { - LLUUID id = material->getSpecularID(); - if (id.notNull()) - { - te_data["material"]["SpecMap"] = id; - } - } - } - LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id); - LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id); - LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id); - LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id); - LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id); - LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id); - LLColor4 spec_color(te_data["material"]["SpecColor"]); - LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); - LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); - LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id); - LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); - if (te_data.has("te") && te_data["te"].has("shiny")) - { - objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger()); - } - } - } - } -} - -struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor -{ - LLPanelFacePasteTexFunctor(LLPanelFace* panel) : - mPanelFace(panel){} - - virtual bool apply(LLViewerObject* objectp, S32 te) - { - mPanelFace->pasteFace(objectp, te); - return true; - } -private: - LLPanelFace *mPanelFace; -}; - -struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor -{ - LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} - virtual bool apply(LLViewerObject* object) - { - object->sendTEUpdate(); - if (mUpdateMedia) - { - LLVOVolume *vo = dynamic_cast(object); - if (vo && vo->hasMedia()) - { - vo->sendMediaDataUpdate(); - } - } - return true; - } -private: - bool mUpdateMedia; -}; - -struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor -{ - virtual bool apply(LLViewerObject* objectp, S32 te) - { - if (objectp && objectp->getTE(te)) - { - LLTextureEntry* tep = objectp->getTE(te); - const LLMediaEntry *media_data = tep->getMediaData(); - if (media_data) - { - if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) - { - viewer_media_t media_impl = - LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); - if (media_impl) - { - media_impl->navigateHome(); - } - } - } - } - return true; - } -}; - -void LLPanelFace::onPasteFaces() -{ - LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); - - LLPanelFacePasteTexFunctor paste_func(this); - selected_objects->applyToTEs(&paste_func); - - LLPanelFaceUpdateFunctor sendfunc(mPasteMedia); - selected_objects->applyToObjects(&sendfunc); - - if (mPasteMedia) - { - LLPanelFaceNavigateHomeFunctor navigate_home_func; - selected_objects->applyToTEs(&navigate_home_func); - } -} - -bool LLPanelFace::pasteCheckMenuItem(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - if ("Color" == command) - { - return mPasteColor; - } - if ("Transparency" == command) - { - return mPasteAlpha; - } - if ("Glow" == command) - { - return mPasteGlow; - } - if ("Diffuse" == command) - { - return mPasteDiffuse; - } - if ("Normal" == command) - { - return mPasteNormal; - } - if ("Specular" == command) - { - return mPasteSpecular; - } - if ("Mapping" == command) - { - return mPasteMapping; - } - if ("Media" == command) - { - return mPasteMedia; - } - - return false; -} - -void LLPanelFace::pasteDoMenuItem(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - if ("Color" == command) - { - mPasteColor = !mPasteColor; - } - if ("Transparency" == command) - { - mPasteAlpha = !mPasteAlpha; - } - if ("Glow" == command) - { - mPasteGlow = !mPasteGlow; - } - if ("Diffuse" == command) - { - mPasteDiffuse = !mPasteDiffuse; - } - if ("Normal" == command) - { - mPasteNormal = !mPasteNormal; - } - if ("Specular" == command) - { - mPasteSpecular = !mPasteSpecular; - } - if ("Mapping" == command) - { - mPasteMapping = !mPasteMapping; - } - if ("Media" == command) - { - mPasteMedia = !mPasteMedia; - } -} - -bool LLPanelFace::pasteEnabletMenuItem(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - // Keep at least one option enabled - S32 num_enabled = mPasteColor - + mPasteAlpha - + mPasteGlow - + mPasteDiffuse - + mPasteNormal - + mPasteSpecular - + mPasteMapping - + mPasteMedia; - if ( num_enabled == 1) - { - if ("Color" == command && mPasteColor) - { - return false; - } - if ("Transparency" == command && mPasteAlpha) - { - return false; - } - if ("Glow" == command && mPasteGlow) - { - return false; - } - if ("Diffuse" == command && mPasteDiffuse) - { - return false; - } - if ("Normal" == command && mPasteNormal) - { - return false; - } - if ("Specular" == command && mPasteSpecular) - { - return false; - } - if ("Mapping" == command && mPasteMapping) - { - return false; - } - if ("Media" == command && mPasteMedia) - { - return false; - } - } - - return true; -} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 770f10e2ee..2d57d89a44 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,7 +47,6 @@ class LLUICtrl; class LLViewerObject; class LLFloater; class LLMaterialID; -class LLMenuButton; // Represents an edit for use in replicating the op across one or more materials in the selection set. // @@ -114,8 +113,6 @@ public: LLRender::eTexIndex getTextureChannelToEdit(); - void pasteFace(LLViewerObject* object, S32 te); - protected: void getState(); @@ -208,14 +205,10 @@ protected: static void onClickAutoFix(void*); static void onAlignTexture(void*); - void onCopyFaces(); - void onPasteFaces(); - bool pasteCheckMenuItem(const LLSD& userdata); - void pasteDoMenuItem(const LLSD& userdata); - bool pasteEnabletMenuItem(const LLSD& userdata); - static F32 valueGlow(LLViewerObject* object, S32 face); + + private: bool isAlpha() { return mIsAlpha; } @@ -241,22 +234,6 @@ private: F32 getCurrentShinyOffsetU(); F32 getCurrentShinyOffsetV(); - LLButton *mBtnCopyFaces; - LLButton *mBtnPasteFaces; - LLMenuButton *mBtnPasteMenu; - - LLSD mClipboard; - BOOL mPasteColor; - BOOL mPasteAlpha; - BOOL mPasteGlow; - BOOL mPasteDiffuse; - BOOL mPasteNormal; - BOOL mPasteSpecular; - BOOL mPasteMapping; - BOOL mPasteMedia; - - BOOL mPopulateAllTEs; - // Update visibility of controls to match current UI mode // (e.g. materials vs media editing) // @@ -520,8 +497,6 @@ public: DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID); DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID); DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor); - - DEF_EDIT_MAT_STATE(LLSD, const LLSD&, fromLLSD); }; class LLSelectedTE diff --git a/indra/newview/skins/default/xui/en/menu_texture_paste.xml b/indra/newview/skins/default/xui/en/menu_texture_paste.xml deleted file mode 100644 index be6535b989..0000000000 --- a/indra/newview/skins/default/xui/en/menu_texture_paste.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 1819106970..438fb1e8ed 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -43,7 +43,7 @@ follows="left|top" height="10" layout="topleft" - left_pad="10" + left_pad="15" name="color trans" text_readonly_color="LabelDisabledColor" top="6" @@ -68,7 +68,7 @@ follows="left|top" height="10" layout="topleft" - left_pad="13" + left_pad="15" name="glow label" text_readonly_color="LabelDisabledColor" top="6" @@ -84,7 +84,7 @@ left_delta="0" name="glow" top_pad="4" - width="50" /> + width="80" /> - - - - + Date: Fri, 19 Jun 2020 22:18:31 +0300 Subject: SL-13359 #9 Texture tab --- indra/newview/llpanelface.cpp | 633 ++++++++++++++++++++- indra/newview/llpanelface.h | 20 +- indra/newview/llpanelvolume.cpp | 3 - .../newview/skins/default/xui/en/floater_tools.xml | 6 +- .../skins/default/xui/en/menu_copy_paste_color.xml | 21 + .../default/xui/en/menu_copy_paste_features.xml | 2 +- .../skins/default/xui/en/menu_copy_paste_light.xml | 2 +- .../default/xui/en/menu_copy_paste_object.xml | 2 +- .../default/xui/en/menu_copy_paste_texture.xml | 21 + .../skins/default/xui/en/panel_tools_texture.xml | 51 +- 10 files changed, 740 insertions(+), 21 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_color.xml create mode 100644 indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 778cb77309..6b5d14300f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -45,9 +45,11 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llinventorymodel.h" // gInventory #include "lllineeditor.h" #include "llmaterialmgr.h" #include "llmediaentry.h" +#include "llmenubutton.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "llresmgr.h" @@ -300,7 +302,9 @@ BOOL LLPanelFace::postBuild() { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - + + mMenuClipboardColor = getChild("clipboard_color_params_btn"); + mMenuClipboardTexture = getChild("clipboard_texture_params_btn"); clearCtrls(); @@ -311,7 +315,9 @@ LLPanelFace::LLPanelFace() : LLPanel(), mIsAlpha(false) { - USE_TEXTURE = LLTrans::getString("use_texture"); + USE_TEXTURE = LLTrans::getString("use_texture"); + mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2)); } @@ -1536,6 +1542,10 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } } + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (selected_count == 1); + mMenuClipboardColor->setEnabled(editable && single_volume); + mMenuClipboardTexture->setEnabled(editable && single_volume); // Set variable values for numeric expressions LLCalc* calcp = LLCalc::getInstance(); @@ -2566,6 +2576,625 @@ void LLPanelFace::onAlignTexture(void* userdata) self->alignTestureLayer(); } +void LLPanelFace::onCopyColor() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + return; + } + + if (mClipboardParams.has("color")) + { + mClipboardParams["color"].clear(); + } + else + { + mClipboardParams["color"] = LLSD::emptyArray(); + } + + std::map asset_item_map; + + // a way to resolve situations where source and target have different amount of faces + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + mClipboardParams["color_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + LLSD te_data; + + // asLLSD() includes media + te_data["te"] = tep->asLLSD(); // Note: includes a lot more than just color/alpha/glow + + mClipboardParams["color"].append(te_data); + } + } + } +} + +void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te) +{ + if (!mClipboardParams.has("color")) + { + return; + } + LLSD te_data; + LLSD &clipboard = mClipboardParams["color"]; // array + if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) + { + te_data = *(clipboard.beginArray()); + } + else if (clipboard[te]) + { + te_data = clipboard[te]; + } + else + { + return; + } + + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + if (te_data.has("te")) + { + // Color / Alpha + if (te_data["te"].has("colors")) + { + LLColor4 color = tep->getColor(); + + LLColor4 clip_color; + clip_color.setValue(te_data["te"]["colors"]); + + // Color + color.mV[VRED] = clip_color.mV[VRED]; + color.mV[VGREEN] = clip_color.mV[VGREEN]; + color.mV[VBLUE] = clip_color.mV[VBLUE]; + + // Alpha + color.mV[VALPHA] = clip_color.mV[VALPHA]; + + objectp->setTEColor(te, color); + } + + // Color/fullbright + if (te_data["te"].has("fullbright")) + { + objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger()); + } + + // Glow + if (te_data["te"].has("glow")) + { + objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal()); + } + } + } +} + +void LLPanelFace::onCopyTexture() +{ + + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + return; + } + + if (mClipboardParams.has("texture")) + { + mClipboardParams["texture"].clear(); + } + else + { + mClipboardParams["texture"] = LLSD::emptyArray(); + } + + std::map asset_item_map; + + // a way to resolve situations where source and target have different amount of faces + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + mClipboardParams["texture_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + LLSD te_data; + + // asLLSD() includes media + te_data["te"] = tep->asLLSD(); + te_data["te"]["shiny"] = tep->getShiny(); + te_data["te"]["bumpmap"] = tep->getBumpmap(); + te_data["te"]["bumpshiny"] = tep->getBumpShiny(); + te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright(); + + if (te_data["te"].has("imageid")) + { + LLUUID item_id; + LLUUID id = te_data["te"]["imageid"].asUUID(); + bool full_perm = get_is_library_texture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); + + if (id.notNull() && !full_perm) + { + std::map::iterator iter = asset_item_map.find(id); + if (iter != asset_item_map.end()) + { + item_id = iter->second; + } + else + { + // What this does is simply searches inventory for item with same asset id, + // as result it is Hightly unreliable, leaves little control to user, borderline hack + // but there are little options to preserve permissions - multiple inventory + // items might reference same asset and inventory search is expensive. + item_id = get_copy_free_item_by_asset_id(id); + // record value to avoid repeating inventory search when possible + asset_item_map[id] = item_id; + } + } + + if (id.isNull() + || (!full_perm && item_id.isNull())) + { + if (!LLLocalBitmapMgr::getInstance()->isLocal(id)) + { + te_data["te"].erase("imageid"); + te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + } + te_data["te"]["itemfullperm"] = true; + } + else + { + te_data["te"]["itemfullperm"] = full_perm; + // If full permission object, texture is free to copy, + // but otherwise we need to check inventory and extract permissions + // + // Normally we care only about restrictions for current user and objects + // don't inherit any 'next owner' permissions from texture, so there is + // no need to record item id if full_perm==true + if (!full_perm && item_id.notNull()) + { + //Todo: + // also same thing probably needs to be present in object and volume panels for sculpt and projector images + /* + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (itemp) + { + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + te_data["te"]["imageitemid"] = item_id; + te_data["te"]["itemfullperm"] = itemp->getIsFullPerm(); + if (!itemp->isFinished()) + { + // needed for dropTextureAllFaces + LLInventoryModelBackgroundFetch::instance().start(item_id, false); + } + } + } + */ + } + } + } + + LLMaterialPtr material_ptr = tep->getMaterialParams(); + if (!material_ptr.isNull()) + { + LLSD mat_data; + + mat_data["NormMap"] = material_ptr->getNormalID(); + mat_data["SpecMap"] = material_ptr->getSpecularID(); + + mat_data["NormRepX"] = material_ptr->getNormalRepeatX(); + mat_data["NormRepY"] = material_ptr->getNormalRepeatY(); + mat_data["NormOffX"] = material_ptr->getNormalOffsetX(); + mat_data["NormOffY"] = material_ptr->getNormalOffsetY(); + mat_data["NormRot"] = material_ptr->getNormalRotation(); + + mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX(); + mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY(); + mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX(); + mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY(); + mat_data["SpecRot"] = material_ptr->getSpecularRotation(); + + mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue(); + mat_data["SpecExp"] = material_ptr->getSpecularLightExponent(); + mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity(); + mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff(); + mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode(); + + // Replace no-copy textures, destination texture will get used instead if available + if (mat_data.has("NormMap")) + { + LLUUID id = mat_data["NormMap"].asUUID(); + if (id.notNull() && !get_can_copy_texture(id)) + { + mat_data["NormMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + mat_data["NormMapNoCopy"] = true; + } + + } + if (mat_data.has("SpecMap")) + { + LLUUID id = mat_data["SpecMap"].asUUID(); + if (id.notNull() && !get_can_copy_texture(id)) + { + mat_data["SpecMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + mat_data["SpecMapNoCopy"] = true; + } + + } + + te_data["material"] = mat_data; + } + + mClipboardParams["texture"].append(te_data); + } + } + } +} + +void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) +{ + if (!mClipboardParams.has("texture")) + { + return; + } + LLSD te_data; + LLSD &clipboard = mClipboardParams["texture"]; // array + if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) + { + te_data = *(clipboard.beginArray()); + } + else if (clipboard[te]) + { + te_data = clipboard[te]; + } + else + { + return; + } + + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + if (te_data.has("te")) + { + // Texture + bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + if (te_data["te"].has("imageid")) + { + const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id + LLViewerInventoryItem* itemp_res = NULL; + + if (te_data["te"].has("imageitemid")) + { + LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); + if (item_id.notNull()) + { + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (itemp && itemp->isFinished()) + { + // dropTextureAllFaces will fail if incomplete + itemp_res = itemp; + } + } + } + //todo: + // for case when item got removed from inventory after we pressed 'copy' + /*if (!itemp_res && !full_perm) + { + // todo: fix this, we are often searching same tuxter multiple times (equal to number of faces) + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(imageid); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + // Extremely unreliable and perfomance unfriendly. + // But we need this to check permissions and it is how texture control finds items + for (S32 i = 0; i < items.size(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp && itemp->isFinished()) + { + // dropTextureAllFaces will fail if incomplete + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + itemp_res = itemp; + break; // first match + } + } + } + }*/ + + if (itemp_res) + { + if (te == -1) // all faces + { + LLToolDragAndDrop::dropTextureAllFaces(objectp, + itemp_res, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + else // one face + { + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + itemp_res, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + } + // not an inventory item or no complete items + else if (full_perm) + { + // Either library, local or existed as fullperm when user made a copy + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + objectp->setTEImage(U8(te), image); + } + } + + if (te_data["te"].has("bumpmap")) + { + objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger()); + } + if (te_data["te"].has("bumpshiny")) + { + objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger()); + } + if (te_data["te"].has("bumpfullbright")) + { + objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger()); + } + + // Texture map + if (te_data["te"].has("scales") && te_data["te"].has("scalet")) + { + objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal()); + } + if (te_data["te"].has("offsets") && te_data["te"].has("offsett")) + { + objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal()); + } + if (te_data["te"].has("imagerot")) + { + objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal()); + } + + // Media + if (te_data["te"].has("media_flags")) + { + U8 media_flags = te_data["te"]["media_flags"].asInteger(); + objectp->setTEMediaFlags(te, media_flags); + LLVOVolume *vo = dynamic_cast(objectp); + if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY)) + { + vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/); + } + } + else + { + // Keep media flags on destination unchanged + } + } + + if (te_data.has("material")) + { + LLUUID object_id = objectp->getID(); + + LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + + // Normal + // Replace placeholders with target's + if (te_data["material"].has("NormMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getNormalID(); + if (id.notNull()) + { + te_data["material"]["NormMap"] = id; + } + } + } + LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id); + + // Specular + // Replace placeholders with target's + if (te_data["material"].has("SpecMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getSpecularID(); + if (id.notNull()) + { + te_data["material"]["SpecMap"] = id; + } + } + } + LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id); + LLColor4 spec_color(te_data["material"]["SpecColor"]); + LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); + LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); + LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id); + LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + if (te_data.has("te") && te_data["te"].has("shiny")) + { + objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger()); + } + } + } +} + +enum EPasteMode +{ + PASTE_COLOR, + PASTE_TEXTURE +}; + +struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor +{ + LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) : + mPanelFace(panel), mMode(mode) {} + + virtual bool apply(LLViewerObject* objectp, S32 te) + { + switch (mMode) + { + case PASTE_COLOR: + mPanelFace->onPasteColor(objectp, te); + break; + case PASTE_TEXTURE: + mPanelFace->onPasteTexture(objectp, te); + break; + } + return true; + } +private: + LLPanelFace *mPanelFace; + EPasteMode mMode; +}; + +struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor +{ + LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} + virtual bool apply(LLViewerObject* object) + { + object->sendTEUpdate(); + if (mUpdateMedia) + { + LLVOVolume *vo = dynamic_cast(object); + if (vo && vo->hasMedia()) + { + vo->sendMediaDataUpdate(); + } + } + return true; + } +private: + bool mUpdateMedia; +}; + +struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor +{ + virtual bool apply(LLViewerObject* objectp, S32 te) + { + if (objectp && objectp->getTE(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + const LLMediaEntry *media_data = tep->getMediaData(); + if (media_data) + { + if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) + { + viewer_media_t media_impl = + LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); + if (media_impl) + { + media_impl->navigateHome(); + } + } + } + } + return true; + } +}; + +void LLPanelFace::menuDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste + if (command == "color_paste") + { + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + + LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(false); + selected_objects->applyToObjects(&sendfunc); + } + else if (command == "texture_paste") + { + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + + LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(true); + selected_objects->applyToObjects(&sendfunc); + + LLPanelFaceNavigateHomeFunctor navigate_home_func; + selected_objects->applyToTEs(&navigate_home_func); + } + // copy + else if (command == "color_copy") + { + onCopyColor(); + } + else if (command == "texture_copy") + { + onCopyTexture(); + } +} + +bool LLPanelFace::menuEnableItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste options + if (command == "color_paste") + { + return mClipboardParams.has("color"); + } + else if (command == "texture_paste") + { + return mClipboardParams.has("texture"); + } + return false; +} + // TODO: I don't know who put these in or what these are for??? void LLPanelFace::setMediaURL(const std::string& url) diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 2d57d89a44..5c1fb7f64d 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,6 +47,7 @@ class LLUICtrl; class LLViewerObject; class LLFloater; class LLMaterialID; +class LLMenuButton; // Represents an edit for use in replicating the op across one or more materials in the selection set. // @@ -205,6 +206,16 @@ protected: static void onClickAutoFix(void*); static void onAlignTexture(void*); +public: // needs to be accessible to selection manager + void onCopyColor(); // records all selected faces + void onPasteColor(LLViewerObject* objectp, S32 te); // to specific face + void onCopyTexture(); + void onPasteTexture(LLViewerObject* objectp, S32 te); + +protected: + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); + static F32 valueGlow(LLViewerObject* object, S32 face); @@ -400,7 +411,10 @@ private: * If agent selects texture which is not allowed to be applied for the currently selected object, * all controls of the floater texture picker which allow to apply the texture will be disabled. */ - void onTextureSelectionChanged(LLInventoryItem* itemp); + void onTextureSelectionChanged(LLInventoryItem* itemp); + + LLMenuButton* mMenuClipboardColor; + LLMenuButton* mMenuClipboardTexture; bool mIsAlpha; @@ -415,7 +429,9 @@ private: * up-arrow on a spinner, and avoids running afoul of its throttle. */ bool mUpdateInFlight; - bool mUpdatePending; + bool mUpdatePending; + + LLSD mClipboardParams; public: #if defined(DEF_GET_MAT_STATE) diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index a03e85daff..dd7ef708f2 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -670,9 +670,6 @@ void LLPanelVolume::clearCtrls() mSpinPhysicsRestitution->setEnabled(FALSE); mComboMaterial->setEnabled( FALSE ); - - mMenuClipboardFeatures->setEnabled(false); - mMenuClipboardLight->setEnabled(false); } // diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 6e08be4866..1bbc2302c3 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2,7 +2,7 @@ + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml index dd58658472..4823d74a26 100644 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml @@ -1,7 +1,7 @@ + name="Copy Paste Features Menu"> + name="Copy Paste Light Menu"> + name="Copy Paste Object Menu"> + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 438fb1e8ed..611433bc1d 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -11,6 +11,19 @@ name="Texture" top="0" width="295"> + + width="54" /> + width="77" /> + + top_pad="17" + width="90"> - + + Date: Fri, 19 Jun 2020 22:45:20 +0300 Subject: SL-13359 #9.5 Texture tab --- indra/newview/llpanelface.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 6b5d14300f..f4122cac5f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@ #include "llfontgl.h" // project includes +#include "llagent.h" #include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -45,7 +46,9 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" // gInventory +#include "llinventorymodelbackgroundfetch.h" #include "lllineeditor.h" #include "llmaterialmgr.h" #include "llmediaentry.h" @@ -2773,9 +2776,6 @@ void LLPanelFace::onCopyTexture() // no need to record item id if full_perm==true if (!full_perm && item_id.notNull()) { - //Todo: - // also same thing probably needs to be present in object and volume panels for sculpt and projector images - /* LLViewerInventoryItem* itemp = gInventory.getItem(item_id); if (itemp) { @@ -2793,7 +2793,6 @@ void LLPanelFace::onCopyTexture() } } } - */ } } } @@ -2901,11 +2900,12 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) } } } - //todo: // for case when item got removed from inventory after we pressed 'copy' - /*if (!itemp_res && !full_perm) + // or texture got pasted into previous object + if (!itemp_res && !full_perm) { - // todo: fix this, we are often searching same tuxter multiple times (equal to number of faces) + // Todo: fix this, we are often searching same texture multiple times (equal to number of faces) + // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLAssetIDMatches asset_id_matches(imageid); @@ -2933,7 +2933,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) } } } - }*/ + } if (itemp_res) { @@ -3013,7 +3013,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); // Normal - // Replace placeholders with target's + // Replace placeholders with target's if (te_data["material"].has("NormMapNoCopy")) { LLMaterialPtr material = tep->getMaterialParams(); -- cgit v1.2.3 From a066c9a859bac941298368676356fe667a9f6501 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 22 Jun 2020 19:35:56 +0300 Subject: SL-13359 #10 Indicate face selection in tools floater --- indra/newview/llfloatertools.cpp | 100 ++++++++++++--------- .../newview/skins/default/xui/en/floater_tools.xml | 10 +-- .../default/xui/en/menu_copy_paste_texture.xml | 6 +- 3 files changed, 64 insertions(+), 52 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 0429749e11..c550b81094 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -480,30 +480,61 @@ void LLFloaterTools::refresh() else #endif { - F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); - S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + F32 link_cost = selection->getSelectedLinksetCost(); + S32 link_count = selection->getRootObjectCount(); + S32 object_count = selection->getObjectCount(); - LLCrossParcelFunctor func; - if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) - { - // Selection crosses parcel bounds. - // We don't display remaining land capacity in this case. - const LLStringExplicit empty_str(""); - childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", empty_str); - } - else - { - LLViewerObject* selected_object = mObjectSelection->getFirstObject(); - if (selected_object) - { - // Select a parcel at the currently selected object's position. - LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); - } - else - { - LL_WARNS() << "Failed to get selected object" << LL_ENDL; - } - } + LLCrossParcelFunctor func; + if (!LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) + { + // Unless multiple parcels selected, higlight parcel object is at. + LLViewerObject* selected_object = mObjectSelection->getFirstObject(); + if (selected_object) + { + // Select a parcel at the currently selected object's position. + LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); + } + else + { + LL_WARNS() << "Failed to get selected object" << LL_ENDL; + } + } + + if (object_count == 1) + { + // "selection_faces" shouldn't be visible if not LLToolFace::getInstance() + // But still need to be populated in case user switches + + std::string faces_str = ""; + + for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end();) + { + LLObjectSelection::iterator nextiter = iter++; // not strictly needed, we have only one object + LLSelectNode* node = *nextiter; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + if (!faces_str.empty()) + { + faces_str += ", "; + } + faces_str += llformat("%d", te); + } + } + } + + childSetTextArg("selection_faces", "[FACES_STRING]", faces_str); + } + + bool show_faces = (object_count == 1) + && LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + getChildView("selection_faces")->setVisible(show_faces); LLStringUtil::format_map_t selection_args; selection_args["OBJ_COUNT"] = llformat("%.1d", link_count); @@ -824,7 +855,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); getChildView("selection_count")->setVisible(!land_visible && have_selection); - getChildView("remaining_capacity")->setVisible(!land_visible && have_selection); + getChildView("selection_faces")->setVisible(LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool() + && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1); getChildView("selection_empty")->setVisible(!land_visible && !have_selection); mTab->setVisible(!land_visible); @@ -1181,26 +1213,6 @@ void LLFloaterTools::updateLandImpacts() return; } - S32 rezzed_prims = parcel->getSimWidePrimCount(); - S32 total_capacity = parcel->getSimWideMaxPrimCapacity(); - LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (region) - { - S32 max_tasks_per_region = (S32)region->getMaxTasks(); - total_capacity = llmin(total_capacity, max_tasks_per_region); - } - std::string remaining_capacity_str = ""; - - bool show_mesh_cost = gMeshRepo.meshRezEnabled(); - if (show_mesh_cost) - { - LLStringUtil::format_map_t remaining_capacity_args; - remaining_capacity_args["LAND_CAPACITY"] = llformat("%d", total_capacity - rezzed_prims); - remaining_capacity_str = getString("status_remaining_capacity", remaining_capacity_args); - } - - childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str); - // Update land impacts info in the weights floater LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance("object_weights"); if(object_weights_floater) diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 1bbc2302c3..f5214420b4 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -68,7 +68,7 @@ - [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] + [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] [secondlife:///app/openfloater/object_weights More info] @@ -763,11 +763,12 @@ font="SansSerifSmall" layout="topleft" left="10" - name="selection_count" + name="selection_faces" top_delta="0" visible="false" width="280"> - + Faces selected: [FACES_STRING] + - [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info] diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml index 8267041502..f358affc23 100644 --- a/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml @@ -7,15 +7,15 @@ layout="topleft" name="params_copy" visible="true"> - + - - + + -- cgit v1.2.3 From 23f20c207d1e69c03e2ce2cb9100ad216ac60708 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 23 Jun 2020 22:02:33 +0300 Subject: SL-12688 Warnings part #1 --- indra/newview/llpanelface.cpp | 299 ++++++++++++++------- indra/newview/llpanelface.h | 2 + .../newview/skins/default/xui/en/notifications.xml | 10 + .../skins/default/xui/en/panel_tools_texture.xml | 9 + 4 files changed, 226 insertions(+), 94 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index f4122cac5f..3849e5c8f7 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2579,6 +2579,80 @@ void LLPanelFace::onAlignTexture(void* userdata) self->alignTestureLayer(); } +enum EPasteMode +{ + PASTE_COLOR, + PASTE_TEXTURE +}; + +struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor +{ + LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) : + mPanelFace(panel), mMode(mode) {} + + virtual bool apply(LLViewerObject* objectp, S32 te) + { + switch (mMode) + { + case PASTE_COLOR: + mPanelFace->onPasteColor(objectp, te); + break; + case PASTE_TEXTURE: + mPanelFace->onPasteTexture(objectp, te); + break; + } + return true; + } +private: + LLPanelFace *mPanelFace; + EPasteMode mMode; +}; + +struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor +{ + LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} + virtual bool apply(LLViewerObject* object) + { + object->sendTEUpdate(); + if (mUpdateMedia) + { + LLVOVolume *vo = dynamic_cast(object); + if (vo && vo->hasMedia()) + { + vo->sendMediaDataUpdate(); + } + } + return true; + } +private: + bool mUpdateMedia; +}; + +struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor +{ + virtual bool apply(LLViewerObject* objectp, S32 te) + { + if (objectp && objectp->getTE(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + const LLMediaEntry *media_data = tep->getMediaData(); + if (media_data) + { + if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) + { + viewer_media_t media_impl = + LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); + if (media_impl) + { + media_impl->navigateHome(); + } + } + } + } + return true; + } +}; + void LLPanelFace::onCopyColor() { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); @@ -2625,12 +2699,74 @@ void LLPanelFace::onCopyColor() } } -void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te) +void LLPanelFace::onPasteColor() { if (!mClipboardParams.has("color")) { return; } + + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + // not supposed to happen + LL_WARNS() << "Failed to paste color due to missing or wrong selection" << LL_ENDL; + return; + } + + bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + LLSD &clipboard = mClipboardParams["color"]; // array + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + S32 compare_tes = num_tes; + + if (face_selection_mode) + { + compare_tes = 0; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + compare_tes++; + } + } + } + + // we can copy if single face was copied in edit face mode or if face count matches + if (!((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) + && compare_tes != clipboard.size()) + { + LLSD notif_args; + if (face_selection_mode) + { + static std::string reason = getString("paste_error_face_selection_mismatch"); + notif_args["REASON"] = reason; + } + else + { + static std::string reason = getString("paste_error_object_face_count_mismatch"); + notif_args["REASON"] = reason; + } + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + + LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(false); + selected_objects->applyToObjects(&sendfunc); +} + +void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te) +{ LLSD te_data; LLSD &clipboard = mClipboardParams["color"]; // array if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) @@ -2687,7 +2823,6 @@ void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te) void LLPanelFace::onCopyTexture() { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); @@ -2854,12 +2989,77 @@ void LLPanelFace::onCopyTexture() } } -void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) +void LLPanelFace::onPasteTexture() { if (!mClipboardParams.has("texture")) { return; } + + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + // not supposed to happen + LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL; + return; + } + + bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + LLSD &clipboard = mClipboardParams["texture"]; // array + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + S32 compare_tes = num_tes; + + if (face_selection_mode) + { + compare_tes = 0; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + compare_tes++; + } + } + } + + // we can copy if single face was copied in edit face mode or if face count matches + if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) + && compare_tes != clipboard.size()) + { + LLSD notif_args; + if (face_selection_mode) + { + static std::string reason = getString("paste_error_face_selection_mismatch"); + notif_args["REASON"] = reason; + } + else + { + static std::string reason = getString("paste_error_object_face_count_mismatch"); + notif_args["REASON"] = reason; + } + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + + LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(true); + selected_objects->applyToObjects(&sendfunc); + + LLPanelFaceNavigateHomeFunctor navigate_home_func; + selected_objects->applyToTEs(&navigate_home_func); +} + +void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) +{ LLSD te_data; LLSD &clipboard = mClipboardParams["texture"]; // array if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) @@ -3066,80 +3266,6 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) } } -enum EPasteMode -{ - PASTE_COLOR, - PASTE_TEXTURE -}; - -struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor -{ - LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) : - mPanelFace(panel), mMode(mode) {} - - virtual bool apply(LLViewerObject* objectp, S32 te) - { - switch (mMode) - { - case PASTE_COLOR: - mPanelFace->onPasteColor(objectp, te); - break; - case PASTE_TEXTURE: - mPanelFace->onPasteTexture(objectp, te); - break; - } - return true; - } -private: - LLPanelFace *mPanelFace; - EPasteMode mMode; -}; - -struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor -{ - LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} - virtual bool apply(LLViewerObject* object) - { - object->sendTEUpdate(); - if (mUpdateMedia) - { - LLVOVolume *vo = dynamic_cast(object); - if (vo && vo->hasMedia()) - { - vo->sendMediaDataUpdate(); - } - } - return true; - } -private: - bool mUpdateMedia; -}; - -struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor -{ - virtual bool apply(LLViewerObject* objectp, S32 te) - { - if (objectp && objectp->getTE(te)) - { - LLTextureEntry* tep = objectp->getTE(te); - const LLMediaEntry *media_data = tep->getMediaData(); - if (media_data) - { - if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) - { - viewer_media_t media_impl = - LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); - if (media_impl) - { - media_impl->navigateHome(); - } - } - } - } - return true; - } -}; - void LLPanelFace::menuDoToSelected(const LLSD& userdata) { std::string command = userdata.asString(); @@ -3147,26 +3273,11 @@ void LLPanelFace::menuDoToSelected(const LLSD& userdata) // paste if (command == "color_paste") { - LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); - - LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR); - selected_objects->applyToTEs(&paste_func); - - LLPanelFaceUpdateFunctor sendfunc(false); - selected_objects->applyToObjects(&sendfunc); + onPasteColor(); } else if (command == "texture_paste") { - LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); - - LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); - selected_objects->applyToTEs(&paste_func); - - LLPanelFaceUpdateFunctor sendfunc(true); - selected_objects->applyToObjects(&sendfunc); - - LLPanelFaceNavigateHomeFunctor navigate_home_func; - selected_objects->applyToTEs(&navigate_home_func); + onPasteTexture(); } // copy else if (command == "color_copy") diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 5c1fb7f64d..948d33c2c1 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -208,8 +208,10 @@ protected: public: // needs to be accessible to selection manager void onCopyColor(); // records all selected faces + void onPasteColor(); // to specific face void onPasteColor(LLViewerObject* objectp, S32 te); // to specific face void onCopyTexture(); + void onPasteTexture(); void onPasteTexture(LLViewerObject* objectp, S32 te); protected: diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8a91a1f721..f59ac450f2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8946,6 +8946,16 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran name="okignore" yestext="OK"/> + + +Paste failed. [REASON] + + + + When multiple faces are copied, the target object must have the same number of faces selected. + + + When all faces of an object are copied, the target object must have the same number of faces. + + Date: Wed, 24 Jun 2020 18:57:49 +0300 Subject: SL-12688 Warnings part #2 --- indra/newview/llpanelface.cpp | 64 +++++++++++++++++++++- indra/newview/lltexturectrl.cpp | 19 +++---- indra/newview/lltexturectrl.h | 2 +- .../newview/skins/default/xui/en/notifications.xml | 15 ++++- .../skins/default/xui/en/panel_tools_texture.xml | 4 ++ 5 files changed, 89 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 3849e5c8f7..641a3602c8 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2869,7 +2869,8 @@ void LLPanelFace::onCopyTexture() { LLUUID item_id; LLUUID id = te_data["te"]["imageid"].asUUID(); - bool full_perm = get_is_library_texture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); + bool from_library = get_is_predefined_texture(id); + bool full_perm = from_library || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); if (id.notNull() && !full_perm) { @@ -2890,6 +2891,12 @@ void LLPanelFace::onCopyTexture() } } + if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID())) + { + full_perm = true; + from_library = true; + } + if (id.isNull() || (!full_perm && item_id.isNull())) { @@ -2899,10 +2906,15 @@ void LLPanelFace::onCopyTexture() te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); } te_data["te"]["itemfullperm"] = true; + te_data["te"]["fromlibrary"] = true; } else { te_data["te"]["itemfullperm"] = full_perm; + // from_library is unreliable since we don't get texture item if source object + // is fullperm but it merely means additional checks when assigning texture + te_data["te"]["fromlibrary"] = from_library; + // If full permission object, texture is free to copy, // but otherwise we need to check inventory and extract permissions // @@ -3046,6 +3058,40 @@ void LLPanelFace::onPasteTexture() return; } + bool full_perm = true; + LLSD::array_const_iterator iter = clipboard.beginArray(); + LLSD::array_const_iterator end = clipboard.endArray(); + for (; iter != end; ++iter) + { + const LLSD& te_data = *iter; + if (te_data.has("te")) + { + full_perm &= te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + if (te_data["te"].has("imageitemid")) + { + LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); + if (item_id.notNull()) + { + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (!itemp) + { + // image might be in object's inventory, but it can be not up to date + LLSD notif_args; + static std::string reason = getString("paste_error_inventory_not_found"); + notif_args["REASON"] = reason; + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + } + } + } + } + + if (!full_perm) + { + LLNotificationsUtil::add("FacePasteTexturePermissions"); + } + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); @@ -3082,6 +3128,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) { // Texture bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean(); if (te_data["te"].has("imageid")) { const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id @@ -3098,12 +3145,21 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) // dropTextureAllFaces will fail if incomplete itemp_res = itemp; } + else + { + // Theoretically shouldn't happend, but if it does happen, we + // might need to add a notification to user that paste will fail + // since inventory isn't fully loaded + LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL; + } } } // for case when item got removed from inventory after we pressed 'copy' // or texture got pasted into previous object if (!itemp_res && !full_perm) { + // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable. + LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL; // Todo: fix this, we are often searching same texture multiple times (equal to number of faces) // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work LLViewerInventoryCategory::cat_array_t cats; @@ -3137,11 +3193,13 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) if (itemp_res) { + // from_library is unreliable since we don't get texture item if object is + // fullperm but it merely means additional checks when assigning texture if (te == -1) // all faces { LLToolDragAndDrop::dropTextureAllFaces(objectp, itemp_res, - LLToolDragAndDrop::SOURCE_AGENT, + from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); } else // one face @@ -3149,7 +3207,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) LLToolDragAndDrop::dropTextureOneFace(objectp, te, itemp_res, - LLToolDragAndDrop::SOURCE_AGENT, + from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 2f5be2b32e..b5e4b3608a 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -82,24 +82,23 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1; //static -bool get_is_library_texture(LLUUID image_id) +bool get_is_predefined_texture(LLUUID asset_id) { - if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID()) - || image_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) - || image_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) - || image_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) - || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) + if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) + || asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) + || asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) + || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) { return true; } return false; } -LLUUID get_copy_free_item_by_asset_id(LLUUID image_id) +LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id) { LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(image_id); + LLAssetIDMatches asset_id_matches(asset_id); gInventory.collectDescendentsIf(LLUUID::null, cats, items, @@ -125,13 +124,13 @@ LLUUID get_copy_free_item_by_asset_id(LLUUID image_id) return LLUUID::null; } -bool get_can_copy_texture(LLUUID image_id) +bool get_can_copy_texture(LLUUID asset_id) { // User is allowed to copy a texture if: // library asset or default texture, // or copy perm asset exists in user's inventory - return get_is_library_texture(image_id) || get_copy_free_item_by_asset_id(image_id).notNull(); + return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull(); } LLFloaterTexturePicker::LLFloaterTexturePicker( diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 2b2c5fa237..97e7bb0d20 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -54,7 +54,7 @@ typedef boost::function drag_n_drop_callback typedef boost::function texture_selected_callback; // Helper functions for UI that work with picker -bool get_is_library_texture(LLUUID image_id); +bool get_is_predefined_texture(LLUUID asset_id); // texture picker works by asset ids since objects normaly do // not retain inventory ids as result these functions are looking diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f59ac450f2..196d507507 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8946,7 +8946,7 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran name="okignore" yestext="OK"/> - + + + You applied a texture with limited permissions, object will inherit permissions from texture. + + + + When all faces of an object are copied, the target object must have the same number of faces. + + One or more texture not found in inventory. + Date: Thu, 25 Jun 2020 23:34:22 +0300 Subject: SL-12688 Restored stricter permission requirements You need to own texture in inventory to be able to copy it --- indra/newview/llpanelface.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 641a3602c8..4249a13827 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2870,7 +2870,7 @@ void LLPanelFace::onCopyTexture() LLUUID item_id; LLUUID id = te_data["te"]["imageid"].asUUID(); bool from_library = get_is_predefined_texture(id); - bool full_perm = from_library || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify()); + bool full_perm = from_library; if (id.notNull() && !full_perm) { @@ -2911,8 +2911,6 @@ void LLPanelFace::onCopyTexture() else { te_data["te"]["itemfullperm"] = full_perm; - // from_library is unreliable since we don't get texture item if source object - // is fullperm but it merely means additional checks when assigning texture te_data["te"]["fromlibrary"] = from_library; // If full permission object, texture is free to copy, @@ -2921,7 +2919,7 @@ void LLPanelFace::onCopyTexture() // Normally we care only about restrictions for current user and objects // don't inherit any 'next owner' permissions from texture, so there is // no need to record item id if full_perm==true - if (!full_perm && item_id.notNull()) + if (!full_perm && !from_library && item_id.notNull()) { LLViewerInventoryItem* itemp = gInventory.getItem(item_id); if (itemp) @@ -3193,8 +3191,6 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) if (itemp_res) { - // from_library is unreliable since we don't get texture item if object is - // fullperm but it merely means additional checks when assigning texture if (te == -1) // all faces { LLToolDragAndDrop::dropTextureAllFaces(objectp, -- cgit v1.2.3 From ccf51f173ca80215e5ecb02cdb04724374349de9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 2 Jul 2020 17:21:09 +0300 Subject: SL-12334 Texture UUID is not copied to clipboard from a full-perms object --- indra/newview/llpanelface.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 4249a13827..091ea3764d 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2872,6 +2872,20 @@ void LLPanelFace::onCopyTexture() bool from_library = get_is_predefined_texture(id); bool full_perm = from_library; + if (!full_perm + && objectp->permCopy() + && objectp->permTransfer() + && objectp->permModify()) + { + // If agent created this object and nothing is limiting permissions, mark as full perm + // If agent was granted permission to edit objects owned and created by somebody else, mark full perm + // This check is not perfect since we can't figure out whom textures belong to so this ended up restrictive + std::string creator_app_link; + LLUUID creator_id; + LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link); + full_perm = objectp->mOwnerID == creator_id; + } + if (id.notNull() && !full_perm) { std::map::iterator iter = asset_item_map.find(id); @@ -3056,7 +3070,7 @@ void LLPanelFace::onPasteTexture() return; } - bool full_perm = true; + bool full_perm_object = true; LLSD::array_const_iterator iter = clipboard.beginArray(); LLSD::array_const_iterator end = clipboard.endArray(); for (; iter != end; ++iter) @@ -3064,8 +3078,9 @@ void LLPanelFace::onPasteTexture() const LLSD& te_data = *iter; if (te_data.has("te")) { - full_perm &= te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); - if (te_data["te"].has("imageitemid")) + bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + full_perm_object &= full_perm; + if (!full_perm && te_data["te"].has("imageitemid")) { LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); if (item_id.notNull()) @@ -3085,7 +3100,7 @@ void LLPanelFace::onPasteTexture() } } - if (!full_perm) + if (!full_perm_object) { LLNotificationsUtil::add("FacePasteTexturePermissions"); } -- cgit v1.2.3 From 3fde31b61026f9052243a5a716dbc0a6419880ae Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 2 Jul 2020 18:36:19 +0300 Subject: SL-12688 Fixed Warning --- indra/newview/llpanelface.cpp | 50 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 091ea3764d..a3f9acb85a 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2911,18 +2911,6 @@ void LLPanelFace::onCopyTexture() from_library = true; } - if (id.isNull() - || (!full_perm && item_id.isNull())) - { - if (!LLLocalBitmapMgr::getInstance()->isLocal(id)) - { - te_data["te"].erase("imageid"); - te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); - } - te_data["te"]["itemfullperm"] = true; - te_data["te"]["fromlibrary"] = true; - } - else { te_data["te"]["itemfullperm"] = full_perm; te_data["te"]["fromlibrary"] = from_library; @@ -3076,26 +3064,40 @@ void LLPanelFace::onPasteTexture() for (; iter != end; ++iter) { const LLSD& te_data = *iter; - if (te_data.has("te")) + if (te_data.has("te") && te_data["te"].has("imageid")) { bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); full_perm_object &= full_perm; - if (!full_perm && te_data["te"].has("imageitemid")) + if (!full_perm) { - LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); - if (item_id.notNull()) + if (te_data["te"].has("imageitemid")) { - LLViewerInventoryItem* itemp = gInventory.getItem(item_id); - if (!itemp) + LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); + if (item_id.notNull()) { - // image might be in object's inventory, but it can be not up to date - LLSD notif_args; - static std::string reason = getString("paste_error_inventory_not_found"); - notif_args["REASON"] = reason; - LLNotificationsUtil::add("FacePasteFailed", notif_args); - return; + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (!itemp) + { + // image might be in object's inventory, but it can be not up to date + LLSD notif_args; + static std::string reason = getString("paste_error_inventory_not_found"); + notif_args["REASON"] = reason; + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } } } + else + { + // Item was not found on 'copy' stage + // Since this happened at copy, might be better to either show this + // at copy stage or to drop clipboard here + LLSD notif_args; + static std::string reason = getString("paste_error_inventory_not_found"); + notif_args["REASON"] = reason; + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } } } } -- cgit v1.2.3 From 94eea485edf06c48fcbbbf195ee2f8eb9b8616b1 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 7 Jul 2020 16:04:37 +0300 Subject: SL-13545 FIXED The 'Flexible Path' settings can be pasted to the sculpted object --- indra/newview/llpanelvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index dd7ef708f2..cd6ea97243 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -981,7 +981,7 @@ void LLPanelVolume::onPasteFeatures() else { LLVOVolume *volobjp = (LLVOVolume *)objectp; - if (volobjp->setIsFlexible(is_flexible)) + if (volobjp->setIsFlexible(false)) { mObject->sendShapeUpdate(); LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); -- cgit v1.2.3 From 0c88287d26f029c1f6f2cbc62982e63628448737 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 14 Oct 2020 22:35:16 +0300 Subject: build fix --- indra/newview/llfloatermodelpreview.cpp | 55 --------------------------------- 1 file changed, 55 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index b70258a060..b9c03f66a3 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1620,61 +1620,6 @@ void LLFloaterModelPreview::refresh() sInstance->mModelPreview->mDirty = true; } -//static -void LLModelPreview::textureLoadedCallback( - BOOL success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* src_aux, - S32 discard_level, - BOOL final, - void* userdata ) -{ - LLModelPreview* preview = (LLModelPreview*) userdata; - preview->refresh(); - - if(final && preview->mModelLoader) - { - // for areTexturesReady() - if(preview->mModelLoader->mNumOfFetchingTextures > 0) - { - preview->mModelLoader->mNumOfFetchingTextures-- ; - } - } -} - -// static -bool LLModelPreview::lodQueryCallback() -{ - // not the best solution, but model preview belongs to floater - // so it is an easy way to check that preview still exists. - LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; - if (fmp && fmp->mModelPreview) - { - LLModelPreview* preview = fmp->mModelPreview; - if (preview->mLodsQuery.size() > 0) - { - S32 lod = preview->mLodsQuery.back(); - preview->mLodsQuery.pop_back(); - preview->genLODs(lod); - - // return false to continue cycle - return false; - } - } - // nothing to process - return true; -} - -void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) -{ - if (!mLODFrozen) - { - genLODs(lod, 3, enforce_tri_limit); - refresh(); - } -} - LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl) { mStage = stage; -- cgit v1.2.3 From 2f5d44f4b6e029be0593fe46151f8d25c4fa11d3 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Thu, 9 Sep 2021 15:52:35 +0300 Subject: SL-15201 Increased the viewer version to 6.5 for copy-paste viewer --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 4c8366c864..f22d756da3 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.4.23 +6.5.0 -- cgit v1.2.3 From bbdbd6c2dd79adc4749e24c88c9f04755a4b12a1 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 15 Apr 2022 22:14:38 +0300 Subject: SL-17204 FIXED The texture with full permissions is settled on the prim after copying texture from the object with texture with no transfer permission --- indra/newview/llpanelface.cpp | 7 ++++++- indra/newview/lltexturectrl.cpp | 13 ++++++++++--- indra/newview/lltexturectrl.h | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 2ac5022695..f50f587f8f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2873,7 +2873,12 @@ void LLPanelFace::onCopyTexture() // as result it is Hightly unreliable, leaves little control to user, borderline hack // but there are little options to preserve permissions - multiple inventory // items might reference same asset and inventory search is expensive. - item_id = get_copy_free_item_by_asset_id(id); + bool no_transfer = false; + if (objectp->getInventoryItemByAsset(id)) + { + no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm(); + } + item_id = get_copy_free_item_by_asset_id(id, no_transfer); // record value to avoid repeating inventory search when possible asset_item_map[id] = item_id; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index cc912758e2..51ee5b6157 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -95,7 +95,7 @@ bool get_is_predefined_texture(LLUUID asset_id) return false; } -LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id) +LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm) { LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -105,6 +105,8 @@ LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id) items, LLInventoryModel::INCLUDE_TRASH, asset_id_matches); + + LLUUID res; if (items.size()) { for (S32 i = 0; i < items.size(); i++) @@ -117,12 +119,17 @@ LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id) gAgent.getID(), gAgent.getGroupID())) { - return itemp->getUUID(); + bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()); + if (allow_trans != no_trans_perm) + { + return itemp->getUUID(); + } + res = itemp->getUUID(); } } } } - return LLUUID::null; + return res; } bool get_can_copy_texture(LLUUID asset_id) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 4250cf86b8..3769f43737 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -60,7 +60,7 @@ bool get_is_predefined_texture(LLUUID asset_id); // for textures in inventory by asset ids // This search can be performance unfriendly and doesn't warranty // that the texture is original source of asset -LLUUID get_copy_free_item_by_asset_id(LLUUID image_id); +LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); bool get_can_copy_texture(LLUUID image_id); ////////////////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 2445525cc573024f8eb64cabac1e6e3dc3362085 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 19 Apr 2022 02:33:59 +0300 Subject: SL-17231 Copying textures should be disabled if object content was not yet updated --- indra/newview/llpanelface.cpp | 19 ++++++++++++++++++- indra/newview/llpanelface.h | 4 ++++ .../skins/default/xui/en/panel_tools_texture.xml | 4 ++++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index f50f587f8f..d50d42bf2f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -330,6 +330,13 @@ LLPanelFace::~LLPanelFace() } +void LLPanelFace::draw() +{ + updateCopyTexButton(); + + LLPanel::draw(); +} + void LLPanelFace::sendTexture() { LLTextureCtrl* mTextureCtrl = getChild("texture control"); @@ -1522,7 +1529,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (selected_count == 1); mMenuClipboardColor->setEnabled(editable && single_volume); - mMenuClipboardTexture->setEnabled(editable && single_volume); // Set variable values for numeric expressions LLCalc* calcp = LLCalc::getInstance(); @@ -1583,6 +1589,17 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } +void LLPanelFace::updateCopyTexButton() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify() + && !objectp->isPermanentEnforced() && !objectp->isInventoryPending() + && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)); + std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options"); + mMenuClipboardTexture->setToolTip(tooltip); + +} + void LLPanelFace::refresh() { LL_DEBUGS("Materials") << LL_ENDL; diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 948d33c2c1..e3b925c1d4 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -97,6 +97,8 @@ public: LLPanelFace(); virtual ~LLPanelFace(); + void draw(); + void refresh(); void setMediaURL(const std::string& url); void setMediaType(const std::string& mime_type); @@ -129,6 +131,8 @@ protected: void sendMedia(); void alignTestureLayer(); + void updateCopyTexButton(); + // this function is to return TRUE if the drag should succeed. static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index a33d425964..0cbd7fe2dd 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -23,6 +23,10 @@ name="paste_error_inventory_not_found"> One or more texture not found in inventory. + + Paste options + Date: Tue, 26 Apr 2022 19:07:39 +0300 Subject: SL-16026 FIXED Copying only one diffuse texture allows pasting this texture into other types of textures --- indra/newview/llpanelface.cpp | 3 ++- indra/newview/lltooldraganddrop.cpp | 6 ++++-- indra/newview/lltooldraganddrop.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index d50d42bf2f..7fe5b1dd3f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3217,7 +3217,8 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) te, itemp_res, from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); + LLUUID::null, + 0); } } // not an inventory item or no complete items diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 50868d0fa5..f76a2f7f90 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1100,7 +1100,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face, LLInventoryItem* item, LLToolDragAndDrop::ESource source, - const LLUUID& src_id) + const LLUUID& src_id, + S32 tex_channel) { if (hit_face == -1) return; if (!item) @@ -1124,7 +1125,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, if (gFloaterTools->getVisible() && panel_face) { - switch (LLSelectMgr::getInstance()->getTextureChannel()) + tex_channel = (tex_channel > -1) ? tex_channel : LLSelectMgr::getInstance()->getTextureChannel(); + switch (tex_channel) { case 0: diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 24a712029c..4537d73332 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -244,7 +244,8 @@ public: static void dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face, LLInventoryItem* item, ESource source, - const LLUUID& src_id); + const LLUUID& src_id, + S32 tex_channel = -1); static void dropTextureAllFaces(LLViewerObject* hit_obj, LLInventoryItem* item, ESource source, -- cgit v1.2.3 From b08340f1831005ae227577899a64408cc939a12d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Jun 2022 19:43:14 +0300 Subject: SL-17475 Remap models before simplification --- indra/llmath/CMakeLists.txt | 3 + indra/llmath/llvolume.cpp | 42 ++++++++ indra/llmath/llvolume.h | 4 + indra/llmeshoptimizer/llmeshoptimizer.cpp | 170 ++++++++++++++++++++++++++++-- indra/llmeshoptimizer/llmeshoptimizer.h | 70 +++++++++++- indra/llprimitive/lldaeloader.cpp | 2 +- indra/llprimitive/llmodel.cpp | 8 ++ indra/llprimitive/llmodel.h | 1 + indra/newview/llfloatermodelpreview.cpp | 4 +- indra/newview/llmodelpreview.cpp | 81 +++++++++----- indra/newview/llmodelpreview.h | 2 +- 11 files changed, 343 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 552e820127..4617309606 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -4,12 +4,14 @@ project(llmath) include(00-Common) include(LLCommon) +include(LLMeshOptimizer) include(bugsplat) include(Boost) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLMESHOPTIMIZER_INCLUDE_DIRS} ) set(llmath_SOURCE_FILES @@ -109,6 +111,7 @@ add_library (llmath ${llmath_SOURCE_FILES}) target_link_libraries(llmath ${LLCOMMON_LIBRARIES} + ${LLMESHOPTIMIZER_LIBRARIES} ) # Add tests diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 5099920f32..23f372f6e3 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -49,6 +49,7 @@ #include "llsdserialize.h" #include "llvector4a.h" #include "llmatrix4a.h" +#include "llmeshoptimizer.h" #include "lltimer.h" #define DEBUG_SILHOUETTE_BINORMALS 0 @@ -4952,6 +4953,47 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a return a.mV[2] < b.mV[2]; } +void LLVolumeFace::remap() +{ + // generate a remap buffer + std::vector remap(mNumIndices); + S32 remap_vertices_count = LLMeshOptimizer::generateRemapMulti(&remap[0], + NULL, + mNumIndices, + mPositions, + mNormals, + mTexCoords, + mNumVertices); + + // Allocate new buffers + U16* remap_indices = (U16*)ll_aligned_malloc_16(mNumIndices * sizeof(U16)); + + S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF; + LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size); + LLVector4a* remap_normals = remap_positions + remap_vertices_count; + LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count); + + // fill the buffers + LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]); + LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]); + LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]); + LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]); + + // free unused buffers + ll_aligned_free_16(mIndices); + ll_aligned_free<64>(mPositions); + ll_aligned_free_16(mTangents); + + mTangents = NULL; + + mIndices = remap_indices; + mPositions = remap_positions; + mNormals = remap_normals; + mTexCoords = remap_tex_coords; + mNumVertices = remap_vertices_count; + mNumAllocatedVertices = remap_vertices_count; +} + void LLVolumeFace::optimize(F32 angle_cutoff) { LLVolumeFace new_face; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c0b224b1ff..9697952f5b 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -902,6 +902,10 @@ public: typedef std::map, VertexMapData::ComparePosition > PointMap; }; + // Eliminates non unique triangles, takes positions, + // normals and texture coordinates into account. + void remap(); + void optimize(F32 angle_cutoff = 2.f); bool cacheOptimize(); diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index a879389c5a..8570887ddd 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -28,6 +28,9 @@ #include "meshoptimizer.h" +#include "llmath.h" +#include "v2math.h" + LLMeshOptimizer::LLMeshOptimizer() { // Todo: Looks like for memory management, we can add allocator and deallocator callbacks @@ -40,24 +43,173 @@ LLMeshOptimizer::~LLMeshOptimizer() } //static -void LLMeshOptimizer::generateShadowIndexBuffer(U16 *destination, - const U16 *indices, +void LLMeshOptimizer::generateShadowIndexBufferU32(U32 *destination, + const U32 *indices, U64 index_count, - const LLVector4a *vertex_positions, - U64 vertex_count, - U64 vertex_positions_stride + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count ) { - meshopt_generateShadowIndexBuffer(destination, + meshopt_Stream streams[3]; + + S32 index = 0; + if (vertex_positions) + { + streams[index].data = (const float*)vertex_positions; + // Despite being LLVector4a, only x, y and z are in use + streams[index].size = sizeof(F32) * 3; + streams[index].stride = sizeof(F32) * 4; + index++; + } + if (normals) + { + streams[index].data = (const float*)normals; + streams[index].size = sizeof(F32) * 3; + streams[index].stride = sizeof(F32) * 4; + index++; + } + if (text_coords) + { + streams[index].data = (const float*)text_coords; + streams[index].size = sizeof(F32) * 2; + streams[index].stride = sizeof(F32) * 2; + index++; + } + + if (index == 0) + { + // invalid + return; + } + + meshopt_generateShadowIndexBufferMulti(destination, indices, index_count, - (const float*)vertex_positions, // verify that it is correct to convert to float vertex_count, - sizeof(LLVector4a), - vertex_positions_stride + streams, + index ); } +//static +void LLMeshOptimizer::generateShadowIndexBufferU16(U16 *destination, + const U16 *indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count +) +{ + meshopt_Stream streams[3]; + + S32 index = 0; + if (vertex_positions) + { + streams[index].data = (const float*)vertex_positions; + streams[index].size = sizeof(F32) * 3; + streams[index].stride = sizeof(F32) * 4; + index++; + } + if (normals) + { + streams[index].data = (const float*)normals; + streams[index].size = sizeof(F32) * 3; + streams[index].stride = sizeof(F32) * 4; + index++; + } + if (text_coords) + { + streams[index].data = (const float*)text_coords; + streams[index].size = sizeof(F32) * 2; + streams[index].stride = sizeof(F32) * 2; + index++; + } + + if (index == 0) + { + // invalid + return; + } + + meshopt_generateShadowIndexBufferMulti(destination, + indices, + index_count, + vertex_count, + streams, + index); +} + +void LLMeshOptimizer::optimizeVertexCacheU32(U32 * destination, const U32 * indices, U64 index_count, U64 vertex_count) +{ + meshopt_optimizeVertexCache(destination, indices, index_count, vertex_count); +} + +void LLMeshOptimizer::optimizeVertexCacheU16(U16 * destination, const U16 * indices, U64 index_count, U64 vertex_count) +{ + meshopt_optimizeVertexCache(destination, indices, index_count, vertex_count); +} + +size_t LLMeshOptimizer::generateRemapMulti( + unsigned int* remap, + const U32 * indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count) +{ + meshopt_Stream streams[] = { + {(const float*)vertex_positions, sizeof(F32) * 3, sizeof(F32) * 4}, + {(const float*)normals, sizeof(F32) * 3, sizeof(F32) * 4}, + {(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2}, + }; + + return meshopt_generateVertexRemapMulti(&remap[0], indices, index_count, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); +} + +void LLMeshOptimizer::remapIndexBufferU32(U32 * destination_indices, + const U32 * indices, + U64 index_count, + const unsigned int* remap) +{ + meshopt_remapIndexBuffer(destination_indices, indices, index_count, remap); +} + +void LLMeshOptimizer::remapIndexBufferU16(U16 * destination_indices, + const U16 * indices, + U64 index_count, + const unsigned int* remap) +{ + meshopt_remapIndexBuffer(destination_indices, indices, index_count, remap); +} + +void LLMeshOptimizer::remapPositionsBuffer(LLVector4a * destination_vertices, + const LLVector4a * vertex_positions, + U64 vertex_count, + const unsigned int* remap) +{ + meshopt_remapVertexBuffer((float*)destination_vertices, (const float*)vertex_positions, vertex_count, sizeof(LLVector4a), remap); +} + +void LLMeshOptimizer::remapNormalsBuffer(LLVector4a * destination_normalss, + const LLVector4a * normals, + U64 mormals_count, + const unsigned int* remap) +{ + meshopt_remapVertexBuffer((float*)destination_normalss, (const float*)normals, mormals_count, sizeof(LLVector4a), remap); +} + +void LLMeshOptimizer::remapUVBuffer(LLVector2 * destination_uvs, + const LLVector2 * uv_positions, + U64 uv_count, + const unsigned int* remap) +{ + meshopt_remapVertexBuffer((float*)destination_uvs, (const float*)uv_positions, uv_count, sizeof(LLVector2), remap); +} + //static U64 LLMeshOptimizer::simplifyU32(U32 *destination, const U32 *indices, diff --git a/indra/llmeshoptimizer/llmeshoptimizer.h b/indra/llmeshoptimizer/llmeshoptimizer.h index e8dd16dae9..c76f8a5a89 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.h +++ b/indra/llmeshoptimizer/llmeshoptimizer.h @@ -28,7 +28,8 @@ #include "linden_common.h" -#include "llmath.h" +class LLVector4a; +class LLVector2; class LLMeshOptimizer { @@ -36,13 +37,74 @@ public: LLMeshOptimizer(); ~LLMeshOptimizer(); - static void generateShadowIndexBuffer( + static void generateShadowIndexBufferU32( + U32 *destination, + const U32 *indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count); + + static void generateShadowIndexBufferU16( U16 *destination, const U16 *indices, U64 index_count, - const LLVector4a *vertex_positions, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count); + + static void optimizeVertexCacheU32( + U32 *destination, + const U32 *indices, + U64 index_count, + U64 vertex_count); + + static void optimizeVertexCacheU16( + U16 *destination, + const U16 *indices, + U64 index_count, + U64 vertex_count); + + // Remap functions + + static size_t generateRemapMulti( + unsigned int* remap, + const U32 * indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count); + + static void remapIndexBufferU32(U32 * destination_indices, + const U32 * indices, + U64 index_count, + const unsigned int* remap); + + static void remapIndexBufferU16(U16 * destination_indices, + const U16 * indices, + U64 index_count, + const unsigned int* remap); + + + static void remapPositionsBuffer(LLVector4a * destination_vertices, + const LLVector4a * vertex_positions, U64 vertex_count, - U64 vertex_positions_stride); + const unsigned int* remap); + + static void remapNormalsBuffer(LLVector4a * destination_normalss, + const LLVector4a * normals, + U64 mormals_count, + const unsigned int* remap); + + static void remapUVBuffer(LLVector2 * destination_uvs, + const LLVector2 * uv_positions, + U64 uv_count, + const unsigned int* remap); + + // Simplification // returns amount of indices in destiantion // sloppy engages a variant of a mechanizm that does not respect topology as much diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index e89690438e..68654486a4 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -2577,7 +2577,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& mo if (!mNoOptimize) { - ret->optimizeVolumeFaces(); + ret->remapVolumeFaces(); } volume_faces = remainder.size(); diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 204ff63712..a2716ecfab 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -107,6 +107,14 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint ) } } +void LLModel::remapVolumeFaces() +{ + for (U32 i = 0; i < getNumVolumeFaces(); ++i) + { + mVolumeFaces[i].remap(); + } +} + void LLModel::optimizeVolumeFaces() { for (U32 i = 0; i < getNumVolumeFaces(); ++i) diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 3881b1338c..354ceb26b7 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -184,6 +184,7 @@ public: void sortVolumeFacesByMaterialName(); void normalizeVolumeFaces(); void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); + void remapVolumeFaces(); void optimizeVolumeFaces(); void offsetMesh( const LLVector3& pivotPoint ); void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index fe5120376c..58fbdba315 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -741,7 +741,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { case LLModelPreview::MESH_OPTIMIZER_AUTO: case LLModelPreview::MESH_OPTIMIZER_SLOPPY: - case LLModelPreview::MESH_OPTIMIZER_COMBINE: + case LLModelPreview::MESH_OPTIMIZER_PRECISE: mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, mode); break; default: @@ -1745,7 +1745,7 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod) S32 index = lod_source_combo->getCurrentIndex(); if (index == LLModelPreview::MESH_OPTIMIZER_AUTO || index == LLModelPreview::MESH_OPTIMIZER_SLOPPY - || index == LLModelPreview::MESH_OPTIMIZER_COMBINE) + || index == LLModelPreview::MESH_OPTIMIZER_PRECISE) { //rebuild LoD to update triangle counts onLODParamCommit(lod, true); } diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 859d987fc3..707a8b970f 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1223,6 +1223,7 @@ void LLModelPreview::restoreNormals() // returns -1 in case of failure F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, bool sloppy) { + // I. Weld faces together // Figure out buffer size S32 size_indices = 0; S32 size_vertices = 0; @@ -1281,7 +1282,35 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe indices_idx_shift += face.mNumVertices; } - // Now that we have buffers, optimize + // II. Remap. + std::vector remap(size_indices); + S32 size_remap_vertices = LLMeshOptimizer::generateRemapMulti(&remap[0], + combined_indices, + size_indices, + combined_positions, + combined_normals, + combined_tex_coords, + size_vertices); + + // Allocate new buffers + U32* remap_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + + S32 remap_tc_bytes_size = ((size_remap_vertices * sizeof(LLVector2)) + 0xF) & ~0xF; + LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_remap_vertices + remap_tc_bytes_size); + LLVector4a* remap_normals = remap_positions + size_remap_vertices; + LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + size_remap_vertices); + + // fill the buffers + LLMeshOptimizer::remapIndexBufferU32(remap_indices, combined_indices, size_indices, &remap[0]); + LLMeshOptimizer::remapPositionsBuffer(remap_positions, combined_positions, size_vertices, &remap[0]); + LLMeshOptimizer::remapNormalsBuffer(remap_normals, combined_normals, size_vertices, &remap[0]); + LLMeshOptimizer::remapUVBuffer(remap_tex_coords, combined_tex_coords, size_vertices, &remap[0]); + + // free unused buffers + ll_aligned_free<64>(combined_positions); + ll_aligned_free_32(combined_indices); + + // III. Simplify S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% S32 new_indices = 0; @@ -1294,19 +1323,19 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe { target_indices = 3; } + new_indices = LLMeshOptimizer::simplifyU32( output_indices, - combined_indices, + remap_indices, size_indices, - combined_positions, - size_vertices, + remap_positions, + size_remap_vertices, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], target_indices, error_threshold, sloppy, &result_error); - if (result_error < 0) { LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel @@ -1315,24 +1344,25 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe << " original count: " << size_indices << LL_ENDL; } + ll_aligned_free_32(remap_indices); + if (new_indices < 3) { // Model should have at least one visible triangle - ll_aligned_free<64>(combined_positions); + ll_aligned_free<64>(remap_positions); ll_aligned_free_32(output_indices); - ll_aligned_free_32(combined_indices); return -1; } - // repack back into individual faces + // IV. Repack back into individual faces - LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size); - LLVector4a* buffer_normals = buffer_positions + size_vertices; - LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_vertices); + LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_remap_vertices + tc_bytes_size); + LLVector4a* buffer_normals = buffer_positions + size_remap_vertices; + LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_remap_vertices); S32 buffer_idx_size = (size_indices * sizeof(U16) + 0xF) & ~0xF; U16* buffer_indices = (U16*)ll_aligned_malloc_16(buffer_idx_size); - S32* old_to_new_positions_map = new S32[size_vertices]; + S32* old_to_new_positions_map = new S32[size_remap_vertices]; S32 buf_positions_copied = 0; S32 buf_indices_copied = 0; @@ -1350,7 +1380,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe bool copy_triangle = false; S32 range = indices_idx_shift + face.mNumVertices; - for (S32 i = 0; i < size_vertices; i++) + for (S32 i = 0; i < size_remap_vertices; i++) { old_to_new_positions_map[i] = -1; } @@ -1408,9 +1438,9 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } // Copy vertice, normals, tcs - buffer_positions[buf_positions_copied] = combined_positions[idx]; - buffer_normals[buf_positions_copied] = combined_normals[idx]; - buffer_tex_coords[buf_positions_copied] = combined_tex_coords[idx]; + buffer_positions[buf_positions_copied] = remap_positions[idx]; + buffer_normals[buf_positions_copied] = remap_normals[idx]; + buffer_tex_coords[buf_positions_copied] = remap_tex_coords[idx]; old_to_new_positions_map[idx] = buf_positions_copied; @@ -1465,11 +1495,10 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } delete[]old_to_new_positions_map; - ll_aligned_free<64>(combined_positions); + ll_aligned_free<64>(remap_positions); ll_aligned_free<64>(buffer_positions); ll_aligned_free_32(output_indices); ll_aligned_free_16(buffer_indices); - ll_aligned_free_32(combined_indices); if (new_indices < 3 || valid_faces == 0) { @@ -1488,10 +1517,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target { return -1; } - // todo: do not allocate per each face, add one large buffer somewhere - // faces have limited amount of indices + S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF; - U16* output = (U16*)ll_aligned_malloc_16(size); + U16* output_indices = (U16*)ll_aligned_malloc_16(size); S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% @@ -1505,8 +1533,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target { target_indices = 3; } + new_indices = LLMeshOptimizer::simplify( - output, + output_indices, face.mIndices, size_indices, face.mPositions, @@ -1517,7 +1546,6 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target sloppy, &result_error); - if (result_error < 0) { LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx @@ -1534,7 +1562,6 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target // Copy old values new_face = face; - if (new_indices < 3) { if (!sloppy) @@ -1563,13 +1590,13 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target // Assign new values new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF; - LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output, idx_size); + LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output_indices, idx_size); // clear unused values new_face.optimize(); } - ll_aligned_free_16(output); + ll_aligned_free_16(output_indices); if (new_indices < 3) { @@ -1711,7 +1738,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Ideally this should run not per model, // but combine all submodels with origin model as well - if (model_meshopt_mode == MESH_OPTIMIZER_COMBINE) + if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE) { // Run meshoptimizer for each model/object, up to 8 faces in one model. diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 9e32215e6a..727fe79373 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -125,7 +125,7 @@ public: { LOD_FROM_FILE = 0, MESH_OPTIMIZER_AUTO, // automatically selects method based on model or face - MESH_OPTIMIZER_COMBINE, // combines faces into a single model, simplifies, then splits back into faces + MESH_OPTIMIZER_PRECISE, // combines faces into a single model, simplifies, then splits back into faces MESH_OPTIMIZER_SLOPPY, // uses sloppy method, works per face USE_LOD_ABOVE, } eLoDMode; -- cgit v1.2.3 From 45bcefd981e268b158d11d59f2ba9063293986a6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 Jun 2022 16:39:46 +0300 Subject: SL-17475 fix remap causing an assert --- indra/llmath/llvolume.cpp | 4 +-- indra/llmeshoptimizer/llmeshoptimizer.cpp | 59 +++++++++++++++++++++++++++++-- indra/llmeshoptimizer/llmeshoptimizer.h | 13 ++++++- indra/newview/llmodelpreview.cpp | 2 +- 4 files changed, 72 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 23f372f6e3..9efdcd4e8c 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4957,8 +4957,8 @@ void LLVolumeFace::remap() { // generate a remap buffer std::vector remap(mNumIndices); - S32 remap_vertices_count = LLMeshOptimizer::generateRemapMulti(&remap[0], - NULL, + S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], + mIndices, mNumIndices, mPositions, mNormals, diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index 8570887ddd..cb9716a907 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -152,7 +152,7 @@ void LLMeshOptimizer::optimizeVertexCacheU16(U16 * destination, const U16 * indi meshopt_optimizeVertexCache(destination, indices, index_count, vertex_count); } -size_t LLMeshOptimizer::generateRemapMulti( +size_t LLMeshOptimizer::generateRemapMultiU32( unsigned int* remap, const U32 * indices, U64 index_count, @@ -167,7 +167,62 @@ size_t LLMeshOptimizer::generateRemapMulti( {(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2}, }; - return meshopt_generateVertexRemapMulti(&remap[0], indices, index_count, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); + // Remap can function without indices, + // but providing indices helps with removing unused vertices + U64 indeces_cmp = indices ? index_count : vertex_count; + + // meshopt_generateVertexRemapMulti will throw an assert if (indices[i] >= vertex_count) + return meshopt_generateVertexRemapMulti(&remap[0], indices, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); +} + +size_t LLMeshOptimizer::generateRemapMultiU16( + unsigned int* remap, + const U16 * indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count) +{ + meshopt_Stream streams[] = { + {(const float*)vertex_positions, sizeof(F32) * 3, sizeof(F32) * 4}, + {(const float*)normals, sizeof(F32) * 3, sizeof(F32) * 4}, + {(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2}, + }; + + S32 out_of_range_count = 0; + U32* indices_u32 = NULL; + if (indices) + { + indices_u32 = (U32*)ll_aligned_malloc_32(index_count * sizeof(U32)); + for (U64 i = 0; i < index_count; i++) + { + if (indices[i] < vertex_count) + { + indices_u32[i] = indices[i]; + } + else + { + out_of_range_count++; + indices_u32[i] = 0; + } + } + } + + if (out_of_range_count) + { + LL_WARNS() << out_of_range_count << " indexes are out of range." << LL_ENDL; + } + + // Remap can function without indices, + // but providing indices helps with removing unused vertices + U64 indeces_cmp = indices_u32 ? index_count : vertex_count; + + size_t unique = meshopt_generateVertexRemapMulti(&remap[0], indices_u32, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); + + ll_aligned_free_32(indices_u32); + + return unique; } void LLMeshOptimizer::remapIndexBufferU32(U32 * destination_indices, diff --git a/indra/llmeshoptimizer/llmeshoptimizer.h b/indra/llmeshoptimizer/llmeshoptimizer.h index c76f8a5a89..ea965d6b47 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.h +++ b/indra/llmeshoptimizer/llmeshoptimizer.h @@ -68,8 +68,10 @@ public: U64 vertex_count); // Remap functions + // Welds indentical vertexes together. + // Removes unused vertices if indices were provided. - static size_t generateRemapMulti( + static size_t generateRemapMultiU32( unsigned int* remap, const U32 * indices, U64 index_count, @@ -78,6 +80,15 @@ public: const LLVector2 * text_coords, U64 vertex_count); + static size_t generateRemapMultiU16( + unsigned int* remap, + const U16 * indices, + U64 index_count, + const LLVector4a * vertex_positions, + const LLVector4a * normals, + const LLVector2 * text_coords, + U64 vertex_count); + static void remapIndexBufferU32(U32 * destination_indices, const U32 * indices, U64 index_count, diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 707a8b970f..ef791fd80d 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1284,7 +1284,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe // II. Remap. std::vector remap(size_indices); - S32 size_remap_vertices = LLMeshOptimizer::generateRemapMulti(&remap[0], + S32 size_remap_vertices = LLMeshOptimizer::generateRemapMultiU32(&remap[0], combined_indices, size_indices, combined_positions, -- cgit v1.2.3 From b1cbf369cf63f270cb810f640a14420be53035ed Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 Jun 2022 18:33:50 +0300 Subject: SL-17475 Use a shadow indices buffer before simplification --- indra/llmath/llvolume.cpp | 13 +- indra/llmeshoptimizer/llmeshoptimizer.cpp | 16 +-- indra/newview/llmodelpreview.cpp | 225 ++++++++++++++++++------------ indra/newview/llmodelpreview.h | 12 +- 4 files changed, 159 insertions(+), 107 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9efdcd4e8c..04d3e9fc08 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4955,7 +4955,7 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a void LLVolumeFace::remap() { - // generate a remap buffer + // Generate a remap buffer std::vector remap(mNumIndices); S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], mIndices, @@ -4966,26 +4966,29 @@ void LLVolumeFace::remap() mNumVertices); // Allocate new buffers - U16* remap_indices = (U16*)ll_aligned_malloc_16(mNumIndices * sizeof(U16)); + S32 size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF; + U16* remap_indices = (U16*)ll_aligned_malloc_16(size); S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF; LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size); LLVector4a* remap_normals = remap_positions + remap_vertices_count; LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count); - // fill the buffers + // Fill the buffers LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]); LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]); LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]); LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]); - // free unused buffers + // Free unused buffers ll_aligned_free_16(mIndices); ll_aligned_free<64>(mPositions); - ll_aligned_free_16(mTangents); + // Tangets are now invalid + ll_aligned_free_16(mTangents); mTangents = NULL; + // Assign new values mIndices = remap_indices; mPositions = remap_positions; mNormals = remap_normals; diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index cb9716a907..c178348968 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -184,12 +184,6 @@ size_t LLMeshOptimizer::generateRemapMultiU16( const LLVector2 * text_coords, U64 vertex_count) { - meshopt_Stream streams[] = { - {(const float*)vertex_positions, sizeof(F32) * 3, sizeof(F32) * 4}, - {(const float*)normals, sizeof(F32) * 3, sizeof(F32) * 4}, - {(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2}, - }; - S32 out_of_range_count = 0; U32* indices_u32 = NULL; if (indices) @@ -199,7 +193,7 @@ size_t LLMeshOptimizer::generateRemapMultiU16( { if (indices[i] < vertex_count) { - indices_u32[i] = indices[i]; + indices_u32[i] = (U32)indices[i]; } else { @@ -211,14 +205,10 @@ size_t LLMeshOptimizer::generateRemapMultiU16( if (out_of_range_count) { - LL_WARNS() << out_of_range_count << " indexes are out of range." << LL_ENDL; + LL_WARNS() << out_of_range_count << " indices are out of range." << LL_ENDL; } - // Remap can function without indices, - // but providing indices helps with removing unused vertices - U64 indeces_cmp = indices_u32 ? index_count : vertex_count; - - size_t unique = meshopt_generateVertexRemapMulti(&remap[0], indices_u32, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); + size_t unique = generateRemapMultiU32(remap, indices_u32, index_count, vertex_positions, normals, text_coords, vertex_count); ll_aligned_free_32(indices_u32); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index ef791fd80d..4ec2d82350 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1221,7 +1221,7 @@ void LLModelPreview::restoreNormals() // Runs per object, but likely it is a better way to run per model+submodels // returns a ratio of base model indices to resulting indices // returns -1 in case of failure -F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode) { // I. Weld faces together // Figure out buffer size @@ -1258,20 +1258,21 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe { const LLVolumeFace &face = base_model->getVolumeFace(face_idx); - // vertices + // Vertices S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a); LLVector4a::memcpyNonAliased16((F32*)(combined_positions + combined_positions_shift), (F32*)face.mPositions, copy_bytes); - // normals + // Normals LLVector4a::memcpyNonAliased16((F32*)(combined_normals + combined_positions_shift), (F32*)face.mNormals, copy_bytes); - // tex coords + // Tex coords copy_bytes = face.mNumVertices * sizeof(LLVector2); memcpy((void*)(combined_tex_coords + combined_positions_shift), (void*)face.mTexCoords, copy_bytes); combined_positions_shift += face.mNumVertices; - // indices, sadly can't do dumb memcpy for indices, need to adjust each value + // Indices + // Sadly can't do dumb memcpy for indices, need to adjust each value for (S32 i = 0; i < face.mNumIndices; ++i) { U16 idx = face.mIndices[i]; @@ -1282,38 +1283,42 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe indices_idx_shift += face.mNumVertices; } - // II. Remap. - std::vector remap(size_indices); - S32 size_remap_vertices = LLMeshOptimizer::generateRemapMultiU32(&remap[0], - combined_indices, - size_indices, - combined_positions, - combined_normals, - combined_tex_coords, - size_vertices); - - // Allocate new buffers - U32* remap_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + // II. Generate a shadow buffer if nessesary. + // Welds together vertices if possible - S32 remap_tc_bytes_size = ((size_remap_vertices * sizeof(LLVector2)) + 0xF) & ~0xF; - LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_remap_vertices + remap_tc_bytes_size); - LLVector4a* remap_normals = remap_positions + size_remap_vertices; - LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + size_remap_vertices); - - // fill the buffers - LLMeshOptimizer::remapIndexBufferU32(remap_indices, combined_indices, size_indices, &remap[0]); - LLMeshOptimizer::remapPositionsBuffer(remap_positions, combined_positions, size_vertices, &remap[0]); - LLMeshOptimizer::remapNormalsBuffer(remap_normals, combined_normals, size_vertices, &remap[0]); - LLMeshOptimizer::remapUVBuffer(remap_tex_coords, combined_tex_coords, size_vertices, &remap[0]); + U32* shadow_indices = NULL; + // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 + // won't do anything new, model was remaped on a per face basis. + // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + // since 'simplifySloppy' ignores all topology, including normals and uvs. + // Note: simplifySloppy can affect UVs significantly. + if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) + { + // strip normals, reflections should restore relatively correctly + shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, combined_tex_coords, size_vertices); + } + if (simplification_mode == MESH_OPTIMIZER_NO_UVS) + { + // strip uvs, can heavily affect textures + shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, NULL, size_vertices); + } - // free unused buffers - ll_aligned_free<64>(combined_positions); - ll_aligned_free_32(combined_indices); + U32* source_indices = NULL; + if (shadow_indices) + { + source_indices = shadow_indices; + } + else + { + source_indices = combined_indices; + } // III. Simplify S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% - S32 new_indices = 0; + S32 size_new_indices = 0; if (indices_decimator > 0) { @@ -1324,32 +1329,36 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe target_indices = 3; } - new_indices = LLMeshOptimizer::simplifyU32( + size_new_indices = LLMeshOptimizer::simplifyU32( output_indices, - remap_indices, + source_indices, size_indices, - remap_positions, - size_remap_vertices, + combined_positions, + size_vertices, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], target_indices, error_threshold, - sloppy, + simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY, &result_error); if (result_error < 0) { LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << LL_ENDL; } - ll_aligned_free_32(remap_indices); + // free unused buffers + ll_aligned_free_32(combined_indices); + ll_aligned_free_32(shadow_indices); + combined_indices = NULL; + shadow_indices = NULL; - if (new_indices < 3) + if (size_new_indices < 3) { // Model should have at least one visible triangle - ll_aligned_free<64>(remap_positions); + ll_aligned_free<64>(combined_positions); ll_aligned_free_32(output_indices); return -1; @@ -1357,12 +1366,12 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe // IV. Repack back into individual faces - LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_remap_vertices + tc_bytes_size); - LLVector4a* buffer_normals = buffer_positions + size_remap_vertices; - LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_remap_vertices); + LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size); + LLVector4a* buffer_normals = buffer_positions + size_vertices; + LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_vertices); S32 buffer_idx_size = (size_indices * sizeof(U16) + 0xF) & ~0xF; U16* buffer_indices = (U16*)ll_aligned_malloc_16(buffer_idx_size); - S32* old_to_new_positions_map = new S32[size_remap_vertices]; + S32* old_to_new_positions_map = new S32[size_vertices]; S32 buf_positions_copied = 0; S32 buf_indices_copied = 0; @@ -1380,13 +1389,13 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe bool copy_triangle = false; S32 range = indices_idx_shift + face.mNumVertices; - for (S32 i = 0; i < size_remap_vertices; i++) + for (S32 i = 0; i < size_vertices; i++) { old_to_new_positions_map[i] = -1; } // Copy relevant indices and vertices - for (S32 i = 0; i < new_indices; ++i) + for (S32 i = 0; i < size_new_indices; ++i) { U32 idx = output_indices[i]; @@ -1409,19 +1418,19 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe LL_WARNS() << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for" << " model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << " error treshold: " << error_threshold << LL_ENDL; // U16 vertices overflow shouldn't happen, but just in case - new_indices = 0; + size_new_indices = 0; valid_faces = 0; for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx) { - genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false); + genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, simplification_mode); const LLVolumeFace &face = target_model->getVolumeFace(face_idx); - new_indices += face.mNumIndices; + size_new_indices += face.mNumIndices; if (face.mNumIndices >= 3) { valid_faces++; @@ -1429,7 +1438,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } if (valid_faces) { - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } else { @@ -1438,9 +1447,9 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } // Copy vertice, normals, tcs - buffer_positions[buf_positions_copied] = remap_positions[idx]; - buffer_normals[buf_positions_copied] = remap_normals[idx]; - buffer_tex_coords[buf_positions_copied] = remap_tex_coords[idx]; + buffer_positions[buf_positions_copied] = combined_positions[idx]; + buffer_normals[buf_positions_copied] = combined_normals[idx]; + buffer_tex_coords[buf_positions_copied] = combined_tex_coords[idx]; old_to_new_positions_map[idx] = buf_positions_copied; @@ -1495,21 +1504,21 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } delete[]old_to_new_positions_map; - ll_aligned_free<64>(remap_positions); + ll_aligned_free<64>(combined_positions); ll_aligned_free<64>(buffer_positions); ll_aligned_free_32(output_indices); ll_aligned_free_16(buffer_indices); - if (new_indices < 3 || valid_faces == 0) + if (size_new_indices < 3 || valid_faces == 0) { // Model should have at least one visible triangle return -1; } - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } -F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode) { const LLVolumeFace &face = base_model->getVolumeFace(face_idx); S32 size_indices = face.mNumIndices; @@ -1521,9 +1530,36 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF; U16* output_indices = (U16*)ll_aligned_malloc_16(size); + U16* shadow_indices = NULL; + // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 + // won't do anything new, model was remaped on a per face basis. + // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + // since 'simplifySloppy' ignores all topology, including normals and uvs. + if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) + { + U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); + LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, face.mTexCoords, face.mNumVertices); + } + if (simplification_mode == MESH_OPTIMIZER_NO_UVS) + { + U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); + LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, NULL, face.mNumVertices); + } + // Don't run ShadowIndexBuffer for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + + U16* source_indices = NULL; + if (shadow_indices) + { + source_indices = shadow_indices; + } + else + { + source_indices = face.mIndices; + } + S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% - S32 new_indices = 0; + S32 size_new_indices = 0; if (indices_decimator > 0) { @@ -1534,16 +1570,16 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target target_indices = 3; } - new_indices = LLMeshOptimizer::simplify( + size_new_indices = LLMeshOptimizer::simplify( output_indices, - face.mIndices, + source_indices, size_indices, face.mPositions, face.mNumVertices, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], target_indices, error_threshold, - sloppy, + simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY, &result_error); if (result_error < 0) @@ -1551,7 +1587,7 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx << " of model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << " error treshold: " << error_threshold << LL_ENDL; @@ -1562,9 +1598,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target // Copy old values new_face = face; - if (new_indices < 3) + if (size_new_indices < 3) { - if (!sloppy) + if (simplification_mode != MESH_OPTIMIZER_NO_TOPOLOGY) { // meshopt_optimizeSloppy() can optimize triangles away even if target_indices is > 2, // but optimize() isn't supposed to @@ -1588,23 +1624,24 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target else { // Assign new values - new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output - S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF; + new_face.resizeIndices(size_new_indices); // will wipe out mIndices, so new_face can't substitute output + S32 idx_size = (size_new_indices * sizeof(U16) + 0xF) & ~0xF; LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output_indices, idx_size); - // clear unused values + // Clear unused values new_face.optimize(); } ll_aligned_free_16(output_indices); + ll_aligned_free_16(shadow_indices); - if (new_indices < 3) + if (size_new_indices < 3) { // At least one triangle is needed return -1; } - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation, bool enforce_tri_limit) @@ -1740,14 +1777,17 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // but combine all submodels with origin model as well if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE) { - // Run meshoptimizer for each model/object, up to 8 faces in one model. - - // Ideally this should run not per model, - // but combine all submodels with origin model as well - F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); - if (res < 0) + // Run meshoptimizer for each face + for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) { - target_model->copyVolumeFaces(base); + F32 res = genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); + if (res < 0) + { + // Mesh optimizer failed and returned an invalid model + const LLVolumeFace &face = base->getVolumeFace(face_idx); + LLVolumeFace &new_face = target_model->getVolumeFace(face_idx); + new_face = face; + } } } @@ -1756,19 +1796,29 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Run meshoptimizer for each face for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) { - if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0) + if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY) < 0) { // Sloppy failed and returned an invalid model - genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); + genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); } } } if (model_meshopt_mode == MESH_OPTIMIZER_AUTO) { - // Switches between 'combine' method and 'sloppy' based on combine's result. - F32 allowed_ratio_drift = 2.f; - F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + // Remove progressively more data if we can't reach the target. + F32 allowed_ratio_drift = 1.8f; + F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); + + if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) + { + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_NORMALS); + } + + if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) + { + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS); + } if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) { @@ -1776,10 +1826,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Sloppy variant can fail entirely and has issues with precision, // so code needs to do multiple attempts with different decimators. // Todo: this is a bit of a mess, needs to be refined and improved + F32 last_working_decimator = 0.f; F32 last_working_ratio = F32_MAX; - F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); if (sloppy_ratio > 0) { @@ -1802,13 +1853,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // side due to overal lack of precision, and we don't need an ideal result, which // likely does not exist, just a better one, so a partial correction is enough. F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2; - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); } if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio) { // Compensation didn't work, return back to previous decimator - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); } if (sloppy_ratio < 0) @@ -1841,7 +1892,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d && sloppy_decimator > precise_ratio && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case { - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); sloppy_decimator = sloppy_decimator / sloppy_decimation_step; } } @@ -1861,7 +1912,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d else { // Fallback to normal method - precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); } LL_INFOS() << "Model " << target_model->getName() diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 727fe79373..215f44357f 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -225,13 +225,21 @@ private: // Count amount of original models, excluding sub-models static U32 countRootModels(LLModelLoader::model_list models); + typedef enum + { + MESH_OPTIMIZER_FULL, + MESH_OPTIMIZER_NO_NORMALS, + MESH_OPTIMIZER_NO_UVS, + MESH_OPTIMIZER_NO_TOPOLOGY, + } eSimplificationMode; + // Merges faces into single mesh, simplifies using mesh optimizer, // then splits back into faces. // Returns reached simplification ratio. -1 in case of a failure. - F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, bool sloppy); + F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode); // Simplifies specified face using mesh optimizer. // Returns reached simplification ratio. -1 in case of a failure. - F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, bool sloppy); + F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode); protected: friend class LLModelLoader; -- cgit v1.2.3 From dcac3f0514444684c57a97c6e01d32499da345d6 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 15 Jun 2022 17:53:22 +0300 Subject: SL-17577 Allow setting Object for sale for L$0 from Object Profile --- indra/newview/skins/default/xui/en/sidepanel_task_info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 8a3e18707f..1c9d750aa6 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -459,7 +459,7 @@ label="Price: L$" label_width="73" width="150" - min_val="1" + min_val="0" height="20" max_val="999999999" tool_tip="Object cost." /> -- cgit v1.2.3 From f451672b0c549092796a018997152cbeb57418b2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 16 Jun 2022 16:46:04 +0300 Subject: SL-17475 Fix wrong remap buffer size --- indra/llmath/llvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 04d3e9fc08..4a069b0f63 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4956,7 +4956,7 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a void LLVolumeFace::remap() { // Generate a remap buffer - std::vector remap(mNumIndices); + std::vector remap(mNumVertices); S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], mIndices, mNumIndices, -- cgit v1.2.3 From 9f5a38b98ef0e05828de729004447e572d139fd4 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 16 Jun 2022 19:40:33 +0300 Subject: SL-17562 FIXED Grid Options changes position upon reopening of Build Window --- indra/newview/llfloatertools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index c550b81094..77a04bc5d7 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1127,7 +1127,7 @@ void LLFloaterTools::onClickGridOptions() { LLFloater* floaterp = LLFloaterReg::showInstance("build_options"); // position floater next to build tools, not over - floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp)); + floaterp->setShape(gFloaterView->findNeighboringPosition(this, floaterp), true); } // static -- cgit v1.2.3 From e8dd01beecaeea8b67c88ffa2212411e672495b6 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 17 Jun 2022 19:00:38 +0300 Subject: SL-17589 FIXED Camera does not zoom correctly when editing wearables --- indra/newview/llpaneleditwearable.cpp | 3 ++- indra/newview/llviewerwindow.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index be11a4a9f3..6e897e2c7e 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1308,7 +1308,8 @@ void LLPanelEditWearable::changeCamera(U8 subpart) gMorphView->setCameraOffset( subpart_entry->mCameraOffset ); if (gSavedSettings.getBOOL("AppearanceCameraMovement")) { - gMorphView->updateCamera(); + gAgentCamera.setFocusOnAvatar(FALSE, FALSE); + gMorphView->updateCamera(); } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8e565bbdca..f4a0b80548 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -103,7 +103,6 @@ #include "llfilepicker.h" #include "llfirstuse.h" #include "llfloater.h" -#include "llfloaterbuildoptions.h" #include "llfloaterbuyland.h" #include "llfloatercamera.h" #include "llfloaterland.h" -- cgit v1.2.3 From 0c169dd37a82266d42b728ca6d5a7c20ee1ab208 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 21 Jun 2022 23:24:14 +0300 Subject: SL-17590 Telehub beacon sometimes renders black --- indra/newview/pipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index da16c8209f..bd6df4ec37 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3939,7 +3939,7 @@ void LLPipeline::postSort(LLCamera& camera) } LL_PUSH_CALLSTACKS(); // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. - if (LLFloaterTelehub::renderBeacons()) + if (LLFloaterTelehub::renderBeacons() && !sShadowRender) { LLFloaterTelehub::addBeacons(); } -- cgit v1.2.3 From 48d2836ce6277f41c172ae5b68f2cb8845df7ad1 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 20 May 2022 23:19:26 +0300 Subject: SL-17436 Tools floater drops negative Z position for attachments --- indra/newview/llpanelobject.cpp | 10 +++++----- indra/newview/skins/default/xui/en/floater_tools.xml | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 3e6697b3c1..1fd1784d4b 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1661,13 +1661,13 @@ void LLPanelObject::sendPosition(BOOL btn_down) if (!regionp) return; - // Clamp the Z height - const F32 height = newpos.mV[VZ]; - const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); - const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); - if (!mObject->isAttachment()) { + // Clamp the Z height + const F32 height = newpos.mV[VZ]; + const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); + const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); + if ( height < min_height) { newpos.mV[VZ] = min_height; diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index f5214420b4..ade79b8884 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1505,6 +1505,7 @@ even though the user gets a free copy. layout="topleft" left_delta="0" max_val="4096" + min_val="-32" name="Pos Z" text_enabled_color="0 0.8 1 .65" top_pad="3" -- cgit v1.2.3 From 10ab905c96bf979827951146d22e98214bf5a310 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 25 Jun 2022 00:30:51 +0300 Subject: SL-17628 Added attachments can be moved past limit Support 'button up' when losing focus When releasing button far out of view or by refocusing something, button was not commiting. LLPanelObject last call was sendPosition(btn_down) with btn_down true which resulted in missed update. Now it will get one more call with btn_down==false. --- indra/llui/llbutton.cpp | 20 ++++++++++++++++++-- indra/llui/llbutton.h | 2 ++ indra/llui/llspinctrl.cpp | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 0e59fdf519..8028f397f3 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -102,6 +102,7 @@ LLButton::Params::Params() scale_image("scale_image", true), hover_glow_amount("hover_glow_amount"), commit_on_return("commit_on_return", true), + commit_on_capture_lost("commit_on_capture_lost", false), display_pressed_state("display_pressed_state", true), use_draw_context_alpha("use_draw_context_alpha", true), badge("badge"), @@ -165,6 +166,7 @@ LLButton::LLButton(const LLButton::Params& p) mBottomVPad(p.pad_bottom), mHoverGlowStrength(p.hover_glow_amount), mCommitOnReturn(p.commit_on_return), + mCommitOnCaptureLost(p.commit_on_capture_lost), mFadeWhenDisabled(FALSE), mForcePressedState(false), mDisplayPressedState(p.display_pressed_state), @@ -475,6 +477,10 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // We only handle the click if the click both started and ended within us if( hasMouseCapture() ) { + // reset timers before focus change, to not cause + // additional commits if mCommitOnCaptureLost. + resetMouseDownTimer(); + // Always release the mouse gFocusMgr.setMouseCapture( NULL ); @@ -489,8 +495,6 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // Regardless of where mouseup occurs, handle callback if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); - resetMouseDownTimer(); - // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. // If mouseup in the widget, it's been clicked if (pointInView(x, y)) @@ -1195,6 +1199,18 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen void LLButton::onMouseCaptureLost() { + if (mCommitOnCaptureLost + && mMouseDownTimer.getStarted()) + { + if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + + if (mIsToggle) + { + toggleState(); + } + + LLUICtrl::onCommit(); + } resetMouseDownTimer(); } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 572d36996c..ccd31e90c0 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -124,6 +124,7 @@ public: Optional is_toggle, scale_image, commit_on_return, + commit_on_capture_lost, display_pressed_state; Optional hover_glow_amount; @@ -374,6 +375,7 @@ protected: F32 mCurGlowStrength; bool mCommitOnReturn; + bool mCommitOnCaptureLost; bool mFadeWhenDisabled; bool mForcePressedState; bool mDisplayPressedState; diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ee78b82429..ef7c8ec012 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -103,6 +103,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height); up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); + up_button_params.commit_on_capture_lost = true; mUpBtn = LLUICtrlFactory::create(up_button_params); addChild(mUpBtn); @@ -111,6 +112,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height); down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); + down_button_params.commit_on_capture_lost = true; mDownBtn = LLUICtrlFactory::create(down_button_params); addChild(mDownBtn); -- cgit v1.2.3 From 8488d8600905a8f5f8e80513e39a67dce7a8cc84 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 30 Jun 2022 13:22:19 +0300 Subject: SL-17668 Add operation "show in inventory" on in-world avatar attachment --- indra/newview/llviewermenu.cpp | 27 ++++++++++++++++++++++ .../skins/default/xui/en/menu_attachment_self.xml | 7 ++++++ 2 files changed, 34 insertions(+) (limited to 'indra') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8522c2ed55..459bbaa00a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2725,6 +2725,32 @@ void handle_object_touch() send_ObjectDeGrab_message(object, pick); } +void handle_object_show_original() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) + { + return; + } + + LLViewerObject *parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if(parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + + if (!object || object->isAvatar()) + { + return; + } + + show_item_original(object->getAttachmentItemID()); +} static void init_default_item_label(const std::string& item_name) @@ -9510,6 +9536,7 @@ void initialize_menus() // Object pie menu view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); commit.add("Object.Touch", boost::bind(&handle_object_touch)); + commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); commit.add("Object.Delete", boost::bind(&handle_object_delete)); view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index 26b1c86c53..3b91b9df7a 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -33,6 +33,13 @@ function="Object.EnableTouch" name="EnableTouch"/> + + + -- cgit v1.2.3 From a3312328bfd211998e32985e0c4b0ff242b8c8cf Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 28 Jun 2022 10:00:52 -0700 Subject: SL-17510: Fix frequently updating meshes (ex: sculpties) causing expensive octree updates by removing them from the static octree via makeActive --- indra/newview/llvovolume.cpp | 12 ++++++++++++ indra/newview/llvovolume.h | 2 ++ 2 files changed, 14 insertions(+) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bae3d540e3..eee3bbc9cc 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -230,6 +230,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; + mServerVolumeUpdateCount = 0; memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); mMDCImplCount = 0; mLastRiggingInfoLOD = -1; @@ -400,6 +401,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, if (setVolume(volume_params, 0)) { markForUpdate(TRUE); + onVolumeUpdateFromServer(); } } @@ -436,6 +438,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, if (setVolume(volume_params, 0)) { markForUpdate(TRUE); + onVolumeUpdateFromServer(); } S32 res2 = unpackTEMessage(*dp); if (TEM_INVALID == res2) @@ -551,6 +554,15 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } +void LLVOVolume::onVolumeUpdateFromServer() +{ + constexpr U32 UPDATES_UNTIL_ACTIVE = 8; + ++mServerVolumeUpdateCount; + if (mDrawable && !mDrawable->isActive() && mServerVolumeUpdateCount > UPDATES_UNTIL_ACTIVE) + { + mDrawable->makeActive(); + } +} void LLVOVolume::animateTextures() { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4cb7a5481c..cbc7735968 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -170,6 +170,7 @@ public: const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; void markForUpdate(BOOL priority); + void onVolumeUpdateFromServer(); void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; } void faceMappingChanged() { mFaceMappingChanged=TRUE; }; @@ -424,6 +425,7 @@ private: LLPointer mLightTexture; media_list_t mMediaImplList; S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 + U64 mServerVolumeUpdateCount; S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; S32 mMDCImplCount; -- cgit v1.2.3 From 0fbfa6e884e1892b6a7049d669782e3b3704cd2f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 1 Jul 2022 22:37:09 +0300 Subject: SL-17493 Show total object count in object inventory --- indra/newview/llpanelobjectinventory.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 0d987df6ca..cfaa9456be 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -618,7 +618,18 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const if (cat) { - mDisplayName.assign(cat->getName()); + std::string name = cat->getName(); + if (mChildren.size() > 0) + { + // Add item count + // Normally we would be using getLabelSuffix for this + // but object's inventory just uses displaynames + LLStringUtil::format_map_t args; + args["[ITEMS_COUNT]"] = llformat("%d", mChildren.size()); + + name.append(" " + LLTrans::getString("InventoryItemsCount", args)); + } + mDisplayName.assign(name); } return mDisplayName; @@ -1522,6 +1533,8 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root { createViewsForCategory(&contents, inventory_root, new_folder); } + // Refresh for label to add item count + new_folder->refresh(); } } -- cgit v1.2.3 From 21d581ed389fe8a23967332b77e213403a51f908 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 30 Jun 2022 15:23:53 -0700 Subject: SL-17448: Fix LOD/octree update feedback loops causing LOD fluctuations. May also fix octree updates on mere material changes due to general refactoring. --- indra/newview/llvovolume.cpp | 39 ++++++++++++++++++--------------------- indra/newview/llvovolume.h | 4 ++-- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index eee3bbc9cc..074ad35af4 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1758,17 +1758,6 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) } } - bool rigged = false; - - if (!isAnimatedObject()) - { - rigged = isRiggedMesh() && isAttachment(); - } - else - { - rigged = isRiggedMesh() && getControlAvatar() && getControlAvatar()->mPlaying; - } - if (any_valid_boxes) { if (rebuild) @@ -1933,7 +1922,7 @@ void LLVOVolume::updateRelativeXform(bool force_identity) } } -bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &should_update_octree_bounds) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; bool regen_faces = false; @@ -1965,6 +1954,9 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) } compiled = TRUE; + // new_lod > old_lod breaks a feedback loop between LOD updates and + // bounding box updates. + should_update_octree_bounds = should_update_octree_bounds || mSculptChanged || new_lod > old_lod; sNumLODChanges += new_num_faces; if ((S32)getNumTEs() != getVolume()->getNumFaces()) @@ -2024,8 +2016,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) group->dirtyMesh(); } - BOOL compiled = FALSE; - updateRelativeXform(); if (mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -2033,49 +2023,56 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } + BOOL compiled = FALSE; + BOOL should_update_octree_bounds = bool(getRiggedVolume()); + if (mVolumeChanged || mFaceMappingChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); bool was_regen_faces = false; + should_update_octree_bounds = true; if (mVolumeChanged) { - was_regen_faces = lodOrSculptChanged(drawable, compiled); + was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); drawable->setState(LLDrawable::REBUILD_VOLUME); } else if (mSculptChanged || mLODChanged || mColorChanged) { compiled = TRUE; - was_regen_faces = lodOrSculptChanged(drawable, compiled); + was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); } if (!was_regen_faces) { regenFaces(); } - - genBBoxes(FALSE); } else if (mLODChanged || mSculptChanged || mColorChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); compiled = TRUE; - lodOrSculptChanged(drawable, compiled); + lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) { updateRiggedVolume(false); } - genBBoxes(FALSE); } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else { compiled = TRUE; // All it did was move or we changed the texture coordinate offset - genBBoxes(FALSE); } + if (should_update_octree_bounds || !mDrawable->getSpatialExtents()->isFinite3()) + { + // Generate bounding boxes if needed, and update the object's size in the + // octree + genBBoxes(FALSE); + } + // Update face flags updateFaceFlags(); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index cbc7735968..8009c92702 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -233,7 +233,7 @@ public: void updateFaceFlags(); void regenFaces(); - BOOL genBBoxes(BOOL force_global); + BOOL genBBoxes(BOOL force_global); void preRebuild(); virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); @@ -393,7 +393,7 @@ protected: void removeMediaImpl(S32 texture_index) ; private: - bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); + bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &shouldUpdateOctreeBounds); public: -- cgit v1.2.3 From 65fb1c26f1266c68b1c6c663c49e25d9a5d62028 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 1 Jul 2022 14:52:31 -0700 Subject: SL-17448: Be more thorough about generating bounding boxes that don't affect the octree --- indra/newview/llvovolume.cpp | 14 ++++++-------- indra/newview/llvovolume.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 074ad35af4..d86e135116 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1682,7 +1682,7 @@ void LLVOVolume::regenFaces() } } -BOOL LLVOVolume::genBBoxes(BOOL force_global) +BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds) { LL_PROFILE_ZONE_SCOPED; BOOL res = TRUE; @@ -1760,7 +1760,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) if (any_valid_boxes) { - if (rebuild) + if (rebuild && should_update_octree_bounds) { //get the Avatar associated with this object if it's rigged LLVOAvatar* avatar = nullptr; @@ -2066,12 +2066,10 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) // All it did was move or we changed the texture coordinate offset } - if (should_update_octree_bounds || !mDrawable->getSpatialExtents()->isFinite3()) - { - // Generate bounding boxes if needed, and update the object's size in the - // octree - genBBoxes(FALSE); - } + should_update_octree_bounds = should_update_octree_bounds || !mDrawable->getSpatialExtents()->isFinite3(); + // Generate bounding boxes if needed, and update the object's size in the + // octree + genBBoxes(FALSE, should_update_octree_bounds); // Update face flags updateFaceFlags(); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 8009c92702..ce6c155883 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -233,7 +233,7 @@ public: void updateFaceFlags(); void regenFaces(); - BOOL genBBoxes(BOOL force_global); + BOOL genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = FALSE); void preRebuild(); virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); -- cgit v1.2.3 From ed9dbabb5e6e5f48492dc650ec2fd82317008b6f Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 4 Jul 2022 20:25:18 +0300 Subject: SL-17665 Add operation to create a subfolder from selected items in Inventory --- indra/newview/llinventorybridge.cpp | 22 +++ indra/newview/llinventoryfunctions.cpp | 155 +++++++++++++++++++++ indra/newview/llinventoryfunctions.h | 4 + indra/newview/lltoastalertpanel.cpp | 2 +- .../skins/default/xui/en/menu_inventory.xml | 19 +++ .../newview/skins/default/xui/en/notifications.xml | 34 +++++ 6 files changed, 235 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a0de3a2af1..884007d2a6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -792,6 +792,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } + if (isAgentInventory()) + { + items.push_back(std::string("New folder from selected")); + items.push_back(std::string("Subfolder Separator")); + std::set selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs(); + uuid_vec_t ids; + std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); + if (!is_only_items_selected(ids) && !is_only_cats_selected(ids)) + { + disabled_items.push_back(std::string("New folder from selected")); + } + } + if (obj->getIsLinkType()) { items.push_back(std::string("Find Original")); @@ -4266,7 +4279,16 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items.push_back(std::string("Conference Chat Folder")); items.push_back(std::string("IM All Contacts In Folder")); } + + if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren()) + { + items.push_back(std::string("Ungroup folder items")); + } } + else + { + disabled_items.push_back(std::string("New folder from selected")); + } #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index d239b23e83..d8a4340254 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1868,6 +1868,86 @@ void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id) } } +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLInventoryItem* inv_item = gInventory.getItem(*it); + if (inv_item) + { + change_item_parent(*it, new_cat_uuid); + } + else + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (inv_cat) + { + gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false); + } + } + } + + LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory"); + if (!floater_inventory) + { + LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; + return; + } + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); + if (sidepanel_inventory) + { + if (sidepanel_inventory->getActivePanel()) + { + sidepanel_inventory->getActivePanel()->setSelection(new_cat_uuid, TAKE_FOCUS_YES); + LLFolderViewItem* fv_folder = sidepanel_inventory->getActivePanel()->getItemByID(new_cat_uuid); + if (fv_folder) + { + fv_folder->setOpen(TRUE); + } + } + } +} + +bool is_only_cats_selected(const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (!inv_cat) + { + return false; + } + } + return true; +} + +bool is_only_items_selected(const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLViewerInventoryItem* inv_item = gInventory.getItem(*it); + if (!inv_item) + { + return false; + } + } + return true; +} + + +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name) +{ + LLInventoryObject* first_item = gInventory.getObject(*selected_uuids.begin()); + if (!first_item) + { + return; + } + + inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids); + gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); + +} + ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- @@ -2522,6 +2602,81 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile(); } + else if ("new_folder_from_selected" == action) + { + + LLInventoryObject* first_item = gInventory.getObject(*ids.begin()); + if (!first_item) + { + return; + } + const LLUUID& parent_uuid = first_item->getParentUUID(); + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLInventoryObject *item = gInventory.getObject(*it); + if (!item || item->getParentUUID() != parent_uuid) + { + LLNotificationsUtil::add("SameFolderRequired"); + return; + } + } + + LLSD args; + args["DESC"] = LLTrans::getString("New Folder"); + + LLNotificationsUtil::add("CreateSubfolder", args, LLSD(), + [ids](const LLSD& notification, const LLSD& response) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notification, response); + if (opt == 0) + { + std::string settings_name = response["message"].asString(); + + LLInventoryObject::correctInventoryName(settings_name); + if (settings_name.empty()) + { + settings_name = LLTrans::getString("New Folder"); + } + move_items_to_new_subfolder(ids, settings_name); + } + }); + } + else if ("ungroup_folder_items" == action) + { + if (selected_uuid_set.size() == 1) + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin()); + if (!inv_cat) + { + return; + } + const LLUUID &new_cat_uuid = inv_cat->getParentUUID(); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array); + LLInventoryModel::cat_array_t cats = *cat_array; + LLInventoryModel::item_array_t items = *item_array; + + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) + { + LLViewerInventoryCategory* cat = *cat_iter; + if (cat) + { + gInventory.changeCategoryParent(cat, new_cat_uuid, false); + } + } + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) + { + LLViewerInventoryItem* item = *item_iter; + if(item) + { + gInventory.changeItemParent(item, new_cat_uuid, false); + } + } + gInventory.removeCategory(inv_cat->getUUID()); + gInventory.notifyObservers(); + } + } else { std::set::iterator set_iter; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 8915bfa1e0..ba9f157e47 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -93,6 +93,10 @@ LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id); +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name); +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); +bool is_only_cats_selected(const uuid_vec_t& selected_uuids); +bool is_only_items_selected(const uuid_vec_t& selected_uuids); /** Miscellaneous global functions ** ** diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 8baad30e8f..692e8d91a9 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -291,7 +291,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLineEditor->setText(edit_text_contents); std::string notif_name = mNotification->getName(); - if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name)) + if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name) || ("CreateSubfolder" == notif_name)) { mLineEditor->setPrevalidate(&LLTextValidate::validateASCII); } diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 78ca170813..aa3d0ae071 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -912,6 +912,25 @@ function="Inventory.DoToSelected" parameter="apply_settings_parcel" /> + + + + + + + diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6a9039b198..0a3826123c 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -11842,4 +11842,38 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB + + + Name the new folder: + confirm +
+ + [DESC] + +