summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-09-27 17:59:27 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-09-27 17:59:40 +0300
commit3e59ae1c43a70f41fba9cf6ba7d33aeed22d3a9f (patch)
treeaf8f19f6b1eb62f4b6120f81625d5c98e8cca3ca
parent44f2286e42a10270c23ea11e308143948d1e3288 (diff)
SL-17640 Support loading materials from multi-material files
-rw-r--r--indra/newview/llmaterialeditor.cpp167
-rw-r--r--indra/newview/llmaterialeditor.h49
-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
4 files changed, 240 insertions, 26 deletions
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/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"