SL-17640 Support loading materials from multi-material files
parent
44f2286e42
commit
3e59ae1c43
|
|
@ -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())
|
||||
{
|
||||
tinygltf::Scene& scene_in = model.scenes[0];
|
||||
material_name = model.materials[index].name;
|
||||
}
|
||||
else if (model.scenes.size() > 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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue