summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-03-18 01:59:22 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-03-20 03:15:28 +0200
commit166fa85705bd7501a1af81d4b529fa4b83038be7 (patch)
tree7011e1e575804da5baf5af4b1c6af30dd6c29425
parent0aa33a144d392c16eaa419ffefa7c98af2e37834 (diff)
#5543 PBR support for pipette
-rw-r--r--indra/newview/llfloatercolorpicker.cpp16
-rw-r--r--indra/newview/llfloatercolorpicker.h3
-rw-r--r--indra/newview/lltexturectrl.cpp96
-rw-r--r--indra/newview/lltexturectrl.h4
-rw-r--r--indra/newview/lltoolpipette.cpp21
-rw-r--r--indra/newview/lltoolpipette.h7
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
7 files changed, 101 insertions, 47 deletions
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index cd45093856..56e086502a 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -233,7 +233,15 @@ bool LLFloaterColorPicker::postBuild()
childSetCommitCallback("sspin", onTextCommit, (void*)this );
childSetCommitCallback("lspin", onTextCommit, (void*)this );
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1));
+ mPipetteConnection = LLToolPipette::getInstance()->setToolSelectCallback(
+ [this](LLPointer<LLViewerObject> object, S32 te_index)
+ {
+ const LLTextureEntry* entry = object->getTE(te_index);
+ if (entry)
+ {
+ onColorSelect(entry->getColor());
+ }
+ });
return true;
}
@@ -460,10 +468,10 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
}
}
-void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
+// From pipette
+void LLFloaterColorPicker::onColorSelect( const LLColor4 &color )
{
- // Pipete
- selectCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
+ selectCurRgb(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]);
}
void LLFloaterColorPicker::onMouseCaptureLost()
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 5c27fffd08..af199d92a3 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -122,7 +122,7 @@ class LLFloaterColorPicker
void onClickPipette ( );
static void onTextCommit ( LLUICtrl* ctrl, void* data );
static void onImmediateCheck ( LLUICtrl* ctrl, void* data );
- void onColorSelect( const class LLTextureEntry& te );
+ void onColorSelect(const LLColor4& color); // from pipette
private:
// mutators for color values, can raise event to preview changes at object
void selectCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn );
@@ -197,6 +197,7 @@ class LLFloaterColorPicker
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
+ boost::signals2::scoped_connection mPipetteConnection;
};
#endif // LL_LLFLOATERCOLORPICKER_H
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 52ec8c17c1..f0655901f7 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -658,7 +658,10 @@ bool LLFloaterTexturePicker::postBuild()
mSavedFolderState.setApply(false);
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
+ mPipetteConnection = LLToolPipette::getInstance()->setToolSelectCallback([this](LLPointer<LLViewerObject> object, S32 te_index)
+ {
+ onPipetteSelect(object, te_index);
+ });
getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
@@ -1640,39 +1643,88 @@ void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& fi
}
}
-void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
+void LLFloaterTexturePicker::onPipetteSelect(LLPointer<LLViewerObject>& object, S32 te_index)
{
- LLUUID inventory_item_id = findItemID(te.getID(), true);
- if (inventory_item_id.notNull())
+ if (mInventoryPickType == PICK_MATERIAL)
{
- LLToolPipette::getInstance()->setResult(true, "");
- if (mInventoryPickType == PICK_MATERIAL)
- {
- // tes have no data about material ids
- // Plus gltf materials are layered with overrides,
- // which mean that end result might have no id.
- LL_WARNS() << "tes have no data about material ids" << LL_ENDL;
- }
- else
+ // Note: does not copy overrides!
+ LLUUID mat_id = object->getRenderMaterialID(te_index);
+ if (mat_id == BLANK_MATERIAL_ASSET_ID)
{
- setImageID(te.getID());
+ // It's fine if blank material isn't in inventory, just set it
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(mat_id);
setTentative(false);
- }
- mNoCopyTextureSelected = false;
- LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+ mNoCopyTextureSelected = false;
- if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ commitIfImmediateSet();
+ }
+ else if (mat_id.isNull())
{
- // no copy texture
- mNoCopyTextureSelected = true;
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoMaterial"));
}
+ else
+ {
+ LLUUID inventory_item_id = findItemID(mat_id, true);
+ if (inventory_item_id.notNull())
+ {
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(mat_id);
+ setTentative(false);
+
+ mNoCopyTextureSelected = false;
+ LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ mNoCopyTextureSelected = true;
+ }
- commitIfImmediateSet();
+ commitIfImmediateSet();
+ }
+ else
+ {
+ // Not in inventory, can't apply
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoMaterial"));
+ }
+ }
}
else
{
- LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
+ const LLTextureEntry* entry = object->getTE(te_index);
+ if (!entry)
+ {
+ // Whatever was selected is not a face/TE,
+ // no texture to check, so do nothing.
+ // Should not be reachable, if you hit this,
+ // check what happens in pipette tool.
+ llassert(false);
+ return;
+ }
+ LLUUID inventory_item_id = findItemID(entry->getID(), true);
+ if (inventory_item_id.notNull())
+ {
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(entry->getID());
+ setTentative(false);
+
+ mNoCopyTextureSelected = false;
+ LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ mNoCopyTextureSelected = true;
+ }
+
+ commitIfImmediateSet();
+ }
+ else
+ {
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
+ }
}
}
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index e0060474ce..759711ebf7 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -374,7 +374,7 @@ public:
static void onBtnNone(void* userdata);
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, bool user_action);
static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
- void onTextureSelect(const LLTextureEntry& te);
+ void onPipetteSelect(LLPointer<LLViewerObject>& object, S32 te_index);
static void onModeSelect(LLUICtrl* ctrl, void *userdata);
static void onBtnAdd(void* userdata);
@@ -457,6 +457,8 @@ private:
set_image_asset_id_callback mSetImageAssetIDCallback;
set_on_update_image_stats_callback mOnUpdateImageStatsCallback;
+ boost::signals2::scoped_connection mPipetteConnection;
+
bool mBakeTextureEnabled;
bool mLocalTextureEnabled;
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 9e3d435688..6ec25e9512 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -47,8 +47,8 @@
//
LLToolPipette::LLToolPipette()
-: LLTool(std::string("Pipette")),
- mSuccess(true)
+: LLTool(std::string("Pipette"))
+, mSuccess(true)
{
}
@@ -103,15 +103,6 @@ bool LLToolPipette::handleToolTip(S32 x, S32 y, MASK mask)
return true;
}
-void LLToolPipette::setTextureEntry(const LLTextureEntry* entry)
-{
- if (entry)
- {
- mTextureEntry = *entry;
- mSignal(mTextureEntry);
- }
-}
-
void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
{
LLViewerObject* hit_obj = pick_info.getObject();
@@ -120,12 +111,14 @@ void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
// if we clicked on a face of a valid prim, save off texture entry data
if (hit_obj &&
hit_obj->getPCode() == LL_PCODE_VOLUME &&
- pick_info.mObjectFace != -1)
+ pick_info.mObjectFace != -1 &&
+ hit_obj->getNumTEs() > pick_info.mObjectFace)
{
//TODO: this should highlight the selected face only
LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj);
- const LLTextureEntry* entry = hit_obj->getTE(pick_info.mObjectFace);
- LLToolPipette::getInstance()->setTextureEntry(entry);
+
+ LLPointer<LLViewerObject> hit_obj_ptr = hit_obj;
+ LLToolPipette::getInstance()->mSignal(hit_obj_ptr, pick_info.mObjectFace);
}
}
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 6c79674d76..7771f467e5 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -51,16 +51,13 @@ public:
virtual bool handleHover(S32 x, S32 y, MASK mask) override;
virtual bool handleToolTip(S32 x, S32 y, MASK mask) override;
- // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
- typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
- void setToolSelectCallback(const signal_t::slot_type& cb) { mSignal.connect(cb); }
+ typedef boost::signals2::signal<void (LLPointer<LLViewerObject> obj, S32 te_index)> signal_t;
+ boost::signals2::connection setToolSelectCallback(const signal_t::slot_type& cb) { return mSignal.connect(cb); }
void setResult(bool success, const std::string& msg);
- void setTextureEntry(const LLTextureEntry* entry);
static void pickCallback(const LLPickInfo& pick_info);
protected:
- LLTextureEntry mTextureEntry;
signal_t mSignal;
bool mSuccess;
std::string mTooltipMsg;
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1860d38b0e..e022f29b76 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2333,6 +2333,7 @@ For AI Character: Get the closest navigable point to the point provided.
<string name="InventorySingleFolderEmpty">Folder is empty.</string>
<string name="InventorySingleFolderNoMatches">No matches.</string>
<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
+ <string name="InventoryNoMaterial">You do not have a copy of this material in your inventory</string>
<string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>
<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3</string>