summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llinventorymodel.cpp1
-rw-r--r--indra/newview/llmaterialeditor.cpp167
-rw-r--r--indra/newview/llmaterialeditor.h49
-rw-r--r--indra/newview/llpanelvolume.cpp2
-rw-r--r--indra/newview/llselectmgr.cpp69
-rw-r--r--indra/newview/llselectmgr.h1
-rw-r--r--indra/newview/lltooldraganddrop.cpp36
-rw-r--r--indra/newview/lltooldraganddrop.h2
-rw-r--r--indra/newview/llviewerobject.cpp30
-rw-r--r--indra/newview/llviewerobject.h6
-rw-r--r--indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml48
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml2
12 files changed, 346 insertions, 67 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 63152d167d..bbe9330bc7 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2841,6 +2841,7 @@ void LLInventoryModel::createCommonSystemCategories()
gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, true);
gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, true); // folder should exist before user tries to 'landmark this'
gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL, true); // probably should be server created
gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
}
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index a0ab771c7b..4f51030fc0 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -65,6 +65,87 @@ const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal";
const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness";
const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
+LLFloaterComboOptions::LLFloaterComboOptions()
+ : LLFloater(LLSD())
+{
+ buildFromFile("floater_combobox_ok_cancel.xml");
+}
+
+LLFloaterComboOptions::~LLFloaterComboOptions()
+{
+
+}
+
+BOOL LLFloaterComboOptions::postBuild()
+{
+ mConfirmButton = getChild<LLButton>("combo_ok", TRUE);
+ mCancelButton = getChild<LLButton>("combo_cancel", TRUE);
+ mComboOptions = getChild<LLComboBox>("combo_options", TRUE);
+ mComboText = getChild<LLTextBox>("combo_text", TRUE);
+
+ mConfirmButton->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) {onConfirm(); });
+ mCancelButton->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) {onCancel(); });
+
+ return TRUE;
+}
+
+LLFloaterComboOptions* LLFloaterComboOptions::showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::list<std::string> &options)
+{
+ LLFloaterComboOptions* combo_picker = new LLFloaterComboOptions();
+ if (combo_picker)
+ {
+ combo_picker->mCallback = callback;
+ combo_picker->setTitle(title);
+
+ combo_picker->mComboText->setText(description);
+
+ std::list<std::string>::const_iterator iter = options.begin();
+ std::list<std::string>::const_iterator end = options.end();
+ for (; iter != end; iter++)
+ {
+ combo_picker->mComboOptions->addSimpleElement(*iter);
+ }
+ combo_picker->mComboOptions->selectFirstItem();
+
+ combo_picker->openFloater(LLSD(title));
+ combo_picker->setFocus(TRUE);
+ combo_picker->center();
+ }
+ return combo_picker;
+}
+
+LLFloaterComboOptions* LLFloaterComboOptions::showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::string &ok_text,
+ const std::string &cancel_text,
+ const std::list<std::string> &options)
+{
+ LLFloaterComboOptions* combo_picker = showUI(callback, title, description, options);
+ if (combo_picker)
+ {
+ combo_picker->mConfirmButton->setLabel(ok_text);
+ combo_picker->mCancelButton->setLabel(cancel_text);
+ }
+ return combo_picker;
+}
+
+void LLFloaterComboOptions::onConfirm()
+{
+ mCallback(mComboOptions->getSimple(), mComboOptions->getCurrentIndex());
+ closeFloater();
+}
+
+void LLFloaterComboOptions::onCancel()
+{
+ mCallback(std::string(), -1);
+ closeFloater();
+}
class LLMaterialEditorCopiedCallback : public LLInventoryCallback
{
@@ -1129,7 +1210,6 @@ void LLMaterialFilePicker::textureLoadedCallback(BOOL success, LLViewerFetchedTe
{
}
-
void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)
{
tinygltf::TinyGLTF loader;
@@ -1166,10 +1246,48 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)
return;
}
- std::string folder = gDirUtilp->getDirName(filename);
+ if (model_in.materials.size() == 1)
+ {
+ loadMaterial(model_in, filename_lc, 0);
+ }
+ else
+ {
+ std::list<std::string> material_list;
+ std::vector<tinygltf::Material>::const_iterator mat_iter = model_in.materials.begin();
+ std::vector<tinygltf::Material>::const_iterator mat_end = model_in.materials.end();
+ for (; mat_iter != mat_end; mat_iter++)
+ {
+ std::string mat_name = mat_iter->name;
+ if (mat_name.empty())
+ {
+ material_list.push_back("Material " + std::to_string(material_list.size()));
+ }
+ else
+ {
+ material_list.push_back(mat_name);
+ }
+ }
+ LLFloaterComboOptions::showUI(
+ [this, model_in, filename_lc](const std::string& option, S32 index)
+ {
+ loadMaterial(model_in, filename_lc, index);
+ },
+ getString("material_selection_title"),
+ getString("material_selection_text"),
+ material_list
+ );
+ }
+}
+void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename_lc, S32 index)
+{
+ if (model_in.materials.size() < index)
+ {
+ return;
+ }
+ std::string folder = gDirUtilp->getDirName(filename_lc);
- tinygltf::Material material_in = model_in.materials[0];
+ tinygltf::Material material_in = model_in.materials[index];
tinygltf::Model model_out;
model_out.asset.version = "2.0";
@@ -1195,13 +1313,13 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)
mBaseColorFetched, mNormalFetched, mMetallicRoughnessFetched, mEmissiveFetched);
pack_textures(base_color_img, normal_img, mr_img, emissive_img, occlusion_img,
mBaseColorJ2C, mNormalJ2C, mMetallicRoughnessJ2C, mEmissiveJ2C);
-
+
LLUUID base_color_id;
if (mBaseColorFetched.notNull())
{
mBaseColorFetched->forceToSaveRawImage(0, F32_MAX);
base_color_id = mBaseColorFetched->getID();
-
+
if (mBaseColorName.empty())
{
mBaseColorName = MATERIAL_BASE_COLOR_DEFAULT_NAME;
@@ -1253,9 +1371,9 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)
setNormalId(normal_id);
setNormalUploadId(normal_id);
- setFromGltfModel(model_in);
+ setFromGltfModel(model_in, index);
- setFromGltfMetaData(filename_lc, model_in);
+ setFromGltfMetaData(filename_lc, model_in, index);
setHasUnsavedChanges(true);
openFloater();
@@ -1263,11 +1381,11 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)
applyToSelection();
}
-bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_textures)
+bool LLMaterialEditor::setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures)
{
- if (model.materials.size() > 0)
+ if (model.materials.size() > index)
{
- tinygltf::Material& material_in = model.materials[0];
+ const tinygltf::Material& material_in = model.materials[index];
if (set_textures)
{
@@ -1429,7 +1547,7 @@ const std::string LLMaterialEditor::getImageNameFromUri(std::string image_uri, c
* the name of the material, a material description and the names of the
* composite textures.
*/
-void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf::Model& model)
+void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index)
{
// Use the name (without any path/extension) of the file that was
// uploaded as the base of the material name. Then if the name of the
@@ -1443,13 +1561,17 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf
// Extract the name of the scene. Note it is often blank or some very
// generic name like "Scene" or "Default" so using this in the name
// is less useful than you might imagine.
- std::string scene_name;
- if (model.scenes.size() > 0)
+ std::string material_name;
+ if (model.materials.size() > index && !model.materials[index].name.empty())
+ {
+ material_name = model.materials[index].name;
+ }
+ else if (model.scenes.size() > 0)
{
- tinygltf::Scene& scene_in = model.scenes[0];
+ const tinygltf::Scene& scene_in = model.scenes[0];
if (scene_in.name.length())
{
- scene_name = scene_in.name;
+ material_name = scene_in.name;
}
else
{
@@ -1461,13 +1583,13 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf
// scene name isn't present so no point using it
}
- // If we have a valid scene name, use it to build the short and
+ // If we have a valid material or scene name, use it to build the short and
// long versions of the material name. The long version is used
// as you might expect, for the material name. The short version is
// used as part of the image/texture name - the theory is that will
// allow content creators to track the material and the corresponding
// textures
- if (scene_name.length())
+ if (material_name.length())
{
mMaterialNameShort = base_filename;
@@ -1475,7 +1597,7 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf
base_filename <<
" " <<
"(" <<
- scene_name <<
+ material_name <<
")"
);
}
@@ -1496,14 +1618,13 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf
/**
* Extract / derive the names of each composite texture. For each, the
- * index in the first material (we only support 1 material currently) is
- * used to to determine which of the "Images" is used. If the index is -1
- * then that texture type is not present in the material (Seems to be
+ * index is used to to determine which of the "Images" is used. If the index
+ * is -1 then that texture type is not present in the material (Seems to be
* quite common that a material is missing 1 or more types of texture)
*/
- if (model.materials.size() > 0)
+ if (model.materials.size() > index)
{
- const tinygltf::Material& first_material = model.materials[0];
+ const tinygltf::Material& first_material = model.materials[index];
mBaseColorName = MATERIAL_BASE_COLOR_DEFAULT_NAME;
// note: unlike the other textures, base color doesn't have its own entry
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 8a67c3c348..7fd8e950a3 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -32,22 +32,63 @@
#include "llviewertexture.h"
class LLTextureCtrl;
+class LLGLTFMaterial;
+class LLButton;
+class LLComboBox;
+class LLTextBox;
namespace tinygltf
{
class Model;
}
-class LLGLTFMaterial;
+// todo: Consider making into a notification or just merging with
+// presets. Layout is identical to camera/graphics presets so there
+// is no point in having multiple separate xmls and classes.
+class LLFloaterComboOptions : public LLFloater
+{
+public:
+ typedef std::function<void(const std::string&, S32)> combo_callback;
+ LLFloaterComboOptions();
+
+ virtual ~LLFloaterComboOptions();
+ /*virtual*/ BOOL postBuild();
+
+ static LLFloaterComboOptions* showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::list<std::string> &options);
+
+ static LLFloaterComboOptions* showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::string &ok_text,
+ const std::string &cancel_text,
+ const std::list<std::string> &options);
+
+private:
+ void onConfirm();
+ void onCancel();
+
+protected:
+ combo_callback mCallback;
+
+ LLButton *mConfirmButton;
+ LLButton *mCancelButton;
+ LLComboBox *mComboOptions;
+ LLTextBox *mComboText;
+};
class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
{
public:
LLMaterialEditor(const LLSD& key);
- bool setFromGltfModel(tinygltf::Model& model, bool set_textures = false);
+ bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false);
- void setFromGltfMetaData(const std::string& filename, tinygltf::Model& model);
+ void setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index);
// open a file dialog and select a gltf/glb file for import
static void importMaterial();
@@ -165,6 +206,8 @@ public:
// initialize the UI from a default GLTF material
void loadDefaults();
private:
+ void loadMaterial(const tinygltf::Model &model, const std::string &filename_lc, S32 index);
+
friend class LLMaterialFilePicker;
LLUUID mAssetID;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 7ddce19bd0..db37938448 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -1334,7 +1334,7 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
- LLToolDragAndDrop::handleDropTextureProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
volobjp->setLightTextureID(asset_id);
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 8f674afc24..d103141669 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1747,6 +1747,7 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item)
S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces());
bool texture_copied = false;
+ bool updated = false;
for (S32 te = 0; te < num_tes; ++te)
{
if (node->isTESelected(te))
@@ -1755,22 +1756,68 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item)
// without making any copies
if (!texture_copied)
{
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
texture_copied = true;
}
// apply texture for the selected faces
add(LLStatViewer::EDIT_TEXTURE, 1);
object->setTEImage(te, image);
- dialog_refresh_all();
-
- // send the update to the simulator
- object->sendTEUpdate();
+ updated = true;
}
}
+
+ if (updated) // not nessesary? sendTEUpdate update supposed to be done by sendfunc
+ {
+ dialog_refresh_all();
+
+ // send the update to the simulator
+ object->sendTEUpdate();
+ }
}
}
+void LLObjectSelection::applyNoCopyPbrMaterialToTEs(LLViewerInventoryItem* item)
+{
+ if (!item)
+ {
+ return;
+ }
+
+ LLUUID asset_id = item->getAssetUUID();
+
+ for (iterator iter = begin(); iter != end(); ++iter)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = (*iter)->getObject();
+ if (!object)
+ {
+ continue;
+ }
+
+ S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces());
+ bool material_copied = false;
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ //(no-copy) materials must be moved to the object's inventory only once
+ // without making any copies
+ if (!material_copied && asset_id.notNull())
+ {
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ material_copied = true;
+ }
+
+ // apply texture for the selected faces
+ //add(LLStatViewer::EDIT_TEXTURE, 1);
+ object->setRenderMaterialID(te, asset_id, false /*will be sent later*/);
+ }
+ }
+ }
+}
+
+
//-----------------------------------------------------------------------------
// selectionSetImage()
//-----------------------------------------------------------------------------
@@ -1952,12 +1999,11 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
}
};
- // TODO: once PBR starts supporting permissions, implement/figure this out
- /*if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+ if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
- getSelection()->applyNoCopyTextureToTEs(item);
+ getSelection()->applyNoCopyPbrMaterialToTEs(item);
}
- else*/
+ else
{
f setfunc(item, mat_id);
getSelection()->applyToTEs(&setfunc);
@@ -1997,6 +2043,7 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
}
+ dialog_refresh_all();
object->sendTEUpdate();
return true;
}
@@ -2263,7 +2310,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)
{
LLViewerObject *object = mSelectedObjects->getFirstRootObject();
if (!object) return;
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
getSelection()->applyToTEs(&setfunc);
@@ -2323,7 +2370,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id)
{
LLViewerObject *object = mSelectedObjects->getFirstRootObject();
if (!object) return;
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
getSelection()->applyToTEs(&setfunc);
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index cc6815296e..573eea7a8a 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -368,6 +368,7 @@ public:
* Then this only texture is used for all selected faces.
*/
void applyNoCopyTextureToTEs(LLViewerInventoryItem* item);
+ void applyNoCopyPbrMaterialToTEs(LLViewerInventoryItem* item);
ESelectType getSelectType() const { return mSelectType; }
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index be42e6f2b2..dd6ac89cc3 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -923,17 +923,17 @@ void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
}
// static
-BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
+BOOL LLToolDragAndDrop::handleDropMaterialProtections(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
const LLUUID& src_id)
{
// Always succeed if....
- // texture is from the library
+ // material is from the library
// or already in the contents of the object
if (SOURCE_LIBRARY == source)
{
- // dropping a texture from the library always just works.
+ // dropping a material from the library always just works.
return TRUE;
}
@@ -964,15 +964,15 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
- // Check that we can add the texture as inventory to the object
+ // Check that we can add the material as inventory to the object
if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
{
return FALSE;
}
- // make sure the object has the texture in it's inventory.
+ // make sure the object has the material in it's inventory.
if (SOURCE_AGENT == source)
{
- // Remove the texture from local inventory. The server
+ // Remove the material from local inventory. The server
// will actually remove the item from agent inventory.
gInventory.deleteObject(item->getUUID());
gInventory.notifyObservers();
@@ -994,10 +994,11 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
}
}
// Add the texture item to the target object's inventory.
- if (LLAssetType::AT_TEXTURE == new_item->getType())
- {
- hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
- }
+ if (LLAssetType::AT_TEXTURE == new_item->getType()
+ || LLAssetType::AT_MATERIAL == new_item->getType())
+ {
+ hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
+ }
else
{
hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
@@ -1016,9 +1017,10 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
// *FIX: may want to make sure agent can paint hit_obj.
// Add the texture item to the target object's inventory.
- if (LLAssetType::AT_TEXTURE == new_item->getType())
+ if (LLAssetType::AT_TEXTURE == new_item->getType()
+ || LLAssetType::AT_MATERIAL == new_item->getType())
{
- hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
+ hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
}
else
{
@@ -1045,7 +1047,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
@@ -1078,7 +1080,7 @@ void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
@@ -1104,7 +1106,7 @@ void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
@@ -1128,7 +1130,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if(!success)
{
return;
@@ -1165,7 +1167,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index cfdbd931ce..bf35840964 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -94,7 +94,7 @@ public:
// deal with permissions of object, etc. returns TRUE if drop can
// proceed, otherwise FALSE.
- static BOOL handleDropTextureProtections(LLViewerObject* hit_obj,
+ static BOOL handleDropMaterialProtections(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
const LLUUID& src_id);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 4e866658a6..b4fad16dba 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3498,11 +3498,11 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
++mExpectedInventorySerialNum;
}
-bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
+bool LLViewerObject::isAssetInInventory(LLViewerInventoryItem* item)
{
bool result = false;
- if (item && LLAssetType::AT_TEXTURE == item->getType())
+ if (item)
{
std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin();
std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end();
@@ -3516,13 +3516,27 @@ bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
return result;
}
-void LLViewerObject::updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new)
+void LLViewerObject::updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new)
{
- if (item && !isTextureInInventory(item))
- {
- mPendingInventoryItemsIDs.push_back(item->getAssetUUID());
- updateInventory(item, key, is_new);
- }
+ if (!item)
+ {
+ return;
+ }
+ if (LLAssetType::AT_TEXTURE != item->getType()
+ && LLAssetType::AT_MATERIAL != item->getType())
+ {
+ // Not supported
+ return;
+ }
+
+ if (isAssetInInventory(item))
+ {
+ // already there
+ return;
+ }
+
+ mPendingInventoryItemsIDs.push_back(item->getAssetUUID());
+ updateInventory(item, key, is_new);
}
void LLViewerObject::updateInventory(
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 1bb67fa80f..9d80f095c9 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -490,7 +490,7 @@ public:
// manager until we have better iterators.
void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
- void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
+ void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
LLInventoryObject* getInventoryObject(const LLUUID& item_id);
// Get content except for root category
@@ -499,8 +499,6 @@ public:
LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
S16 getInventorySerial() const { return mInventorySerialNum; }
- bool isTextureInInventory(LLViewerInventoryItem* item);
-
// These functions does viewer-side only object inventory modifications
void updateViewerInventoryAsset(
const LLViewerInventoryItem* item,
@@ -629,6 +627,8 @@ public:
std::vector<LLVector3> mUnselectedChildrenPositions ;
private:
+ bool isAssetInInventory(LLViewerInventoryItem* item);
+
ExtraParameter* createNewParameterEntry(U16 param_type);
ExtraParameter* getExtraParameterEntry(U16 param_type) const;
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
diff --git a/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml b/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml
new file mode 100644
index 0000000000..63eaffde18
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<floater
+ legacy_header_height="18"
+ height="130"
+ min_height="130"
+ width="270"
+ min_width="270"
+ layout="topleft"
+ name="floater_combo"
+ title="floater_combo"
+ help_topic="floater_combo"
+ can_resize="false"
+ can_minimize="false">
+ <text
+ follows="top|left|right"
+ height="10"
+ layout="topleft"
+ left="20"
+ name="combo_text"
+ top="30"
+ width="200">
+ Select an option:
+ </text>
+ <combo_box
+ follows="top|left"
+ layout="topleft"
+ left="20"
+ name="combo_options"
+ top_delta="20"
+ width="230"/>
+ <button
+ follows="top|left"
+ height="23"
+ label="OK"
+ layout="topleft"
+ top_delta="40"
+ left="20"
+ name="combo_ok"
+ width="90"/>
+ <button
+ follows="top|left"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ left_pad="50"
+ name="combo_cancel"
+ width="90"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml
index 67cbb253d9..3314d49ac3 100644
--- a/indra/newview/skins/default/xui/en/floater_material_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -13,6 +13,8 @@
title="[MATERIAL_NAME]">
<string name="no_upload_fee_string">no upload fee</string>
<string name="upload_fee_string">L$[FEE] upload fee</string>
+ <string name="material_selection_title">Material selection</string>
+ <string name="material_selection_text">Select material:</string>
<scroll_container
name="materials_scroll"