SL-17605 WIP - Upload->Material now lets you pick a GLTF file and imports the first material in the GLTF file to the Material Editor

master
Dave Parks 2022-06-15 17:03:38 -05:00
parent ad533fcd6b
commit f5d66e79ee
6 changed files with 314 additions and 2 deletions

View File

@ -60,6 +60,7 @@ LLFilePicker LLFilePicker::sInstance;
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
#define MODEL_FILTER L"Model files (*.dae; *.gltf; *.glb)\0*.dae;*.gltf;*.glb\0"
#define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
#endif
@ -215,6 +216,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = MODEL_FILTER \
L"\0";
break;
case FFLOAD_MATERIAL:
mOFN.lpstrFilter = MATERIAL_FILTER \
L"\0";
break;
case FFLOAD_SCRIPT:
mOFN.lpstrFilter = SCRIPT_FILTER \
L"\0";

View File

@ -86,7 +86,8 @@ public:
FFLOAD_SCRIPT = 11,
FFLOAD_DICTIONARY = 12,
FFLOAD_DIRECTORY = 13, // To call from lldirpicker.
FFLOAD_EXE = 14 // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
FFLOAD_MATERIAL = 15
};
enum ESaveFilter

View File

@ -28,6 +28,9 @@
#include "llmaterialeditor.h"
#include "llcombobox.h"
#include "llviewermenufile.h"
#include "llappviewer.h"
#include "llviewertexture.h"
#include "tinygltf/tiny_gltf.h"
@ -52,6 +55,11 @@ LLUUID LLMaterialEditor::getAlbedoId()
return childGetValue("albedo texture").asUUID();
}
void LLMaterialEditor::setAlbedoId(const LLUUID& id)
{
childSetValue("albedo texture", id);
}
LLColor4 LLMaterialEditor::getAlbedoColor()
{
LLColor4 ret = LLColor4(childGetValue("albedo color"));
@ -60,6 +68,12 @@ LLColor4 LLMaterialEditor::getAlbedoColor()
}
void LLMaterialEditor::setAlbedoColor(const LLColor4& color)
{
childSetValue("albedo color", color.getValue());
childSetValue("transparency", color.mV[3]);
}
F32 LLMaterialEditor::getTransparency()
{
return childGetValue("transparency").asReal();
@ -70,46 +84,91 @@ std::string LLMaterialEditor::getAlphaMode()
return childGetValue("alpha mode").asString();
}
void LLMaterialEditor::setAlphaMode(const std::string& alpha_mode)
{
childSetValue("alpha mode", alpha_mode);
}
F32 LLMaterialEditor::getAlphaCutoff()
{
return childGetValue("alpha cutoff").asReal();
}
void LLMaterialEditor::setAlphaCutoff(F32 alpha_cutoff)
{
childSetValue("alpha cutoff", alpha_cutoff);
}
LLUUID LLMaterialEditor::getMetallicRoughnessId()
{
return childGetValue("metallic-roughness texture").asUUID();
}
void LLMaterialEditor::setMetallicRoughnessId(const LLUUID& id)
{
childSetValue("metallic-roughness texture", id);
}
F32 LLMaterialEditor::getMetalnessFactor()
{
return childGetValue("metalness factor").asReal();
}
void LLMaterialEditor::setMetalnessFactor(F32 factor)
{
childSetValue("metalness factor", factor);
}
F32 LLMaterialEditor::getRoughnessFactor()
{
return childGetValue("roughness factor").asReal();
}
void LLMaterialEditor::setRoughnessFactor(F32 factor)
{
childSetValue("roughness factor", factor);
}
LLUUID LLMaterialEditor::getEmissiveId()
{
return childGetValue("emissive texture").asUUID();
}
void LLMaterialEditor::setEmissiveId(const LLUUID& id)
{
childSetValue("emissive texture", id);
}
LLColor4 LLMaterialEditor::getEmissiveColor()
{
return LLColor4(childGetValue("emissive color"));
}
void LLMaterialEditor::setEmissiveColor(const LLColor4& color)
{
childSetValue("emissive color", color.getValue());
}
LLUUID LLMaterialEditor::getNormalId()
{
return childGetValue("normal texture").asUUID();
}
void LLMaterialEditor::setNormalId(const LLUUID& id)
{
childSetValue("normal texture", id);
}
bool LLMaterialEditor::getDoubleSided()
{
return childGetValue("double sided").asBoolean();
}
void LLMaterialEditor::setDoubleSided(bool double_sided)
{
childSetValue("double sided", double_sided);
}
static void write_color(const LLColor4& color, std::vector<double>& c)
{
@ -205,3 +264,185 @@ void LLMaterialEditor::onClickSave()
LL_INFOS() << dump << LL_ENDL;
}
class LLMaterialFilePicker : public LLFilePickerThread
{
public:
LLMaterialFilePicker(LLMaterialEditor* me);
virtual void notify(const std::vector<std::string>& filenames);
void loadMaterial(const std::string& filename);
static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata);
private:
LLMaterialEditor* mME;
};
LLMaterialFilePicker::LLMaterialFilePicker(LLMaterialEditor* me)
: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
{
mME = me;
}
void LLMaterialFilePicker::notify(const std::vector<std::string>& filenames)
{
if (LLAppViewer::instance()->quitRequested())
{
return;
}
if (filenames.size() > 0)
{
loadMaterial(filenames[0]);
}
}
static std::string get_texture_uri(const tinygltf::Model& model, S32 texture_index)
{
std::string ret;
if (texture_index >= 0)
{
S32 source_idx = model.textures[texture_index].source;
if (source_idx >= 0)
{
ret = model.images[source_idx].uri;
}
}
return ret;
}
static LLViewerFetchedTexture* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index)
{
LLViewerFetchedTexture* ret = nullptr;
std::string file = get_texture_uri(model, texture_index);
if (!file.empty())
{
std::string uri = folder;
gDirUtilp->append(uri, file);
ret = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + LLURI::unescape(uri), FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
//ret->setLoadedCallback(LLMaterialFilePicker::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE);
ret->forceToSaveRawImage(0, F32_MAX);
}
return ret;
}
static LLColor4 get_color(const std::vector<double>& in)
{
LLColor4 out;
for (S32 i = 0; i < llmin((S32) in.size(), 4); ++i)
{
out.mV[i] = in[i];
}
return out;
}
void LLMaterialFilePicker::textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata)
{
}
void LLMaterialFilePicker::loadMaterial(const std::string& filename)
{
tinygltf::TinyGLTF loader;
std::string error_msg;
std::string warn_msg;
bool loaded = false;
tinygltf::Model model_in;
std::string filename_lc = filename;
LLStringUtil::toLower(filename_lc);
// Load a tinygltf model fom a file. Assumes that the input filename has already been
// been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
if (std::string::npos == filename_lc.rfind(".gltf"))
{ // file is binary
loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename);
}
else
{ // file is ascii
loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename);
}
if (!loaded)
{
// TODO: show error_msg to user
return;
}
if (model_in.materials.empty())
{
// TODO: show error message that materials are missing
return;
}
std::string folder = gDirUtilp->getDirName(filename);
tinygltf::Material material_in = model_in.materials[0];
tinygltf::Model model_out;
model_out.asset.version = "2.0";
model_out.materials.resize(1);
// get albedo texture
LLPointer<LLViewerFetchedTexture> albedo_tex = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index);
LLUUID albedo_id;
if (albedo_tex != nullptr)
{
albedo_id = albedo_tex->getID();
}
// get metallic-roughness texture
LLPointer<LLViewerFetchedTexture> mr_tex = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index);
LLUUID mr_id;
if (mr_tex != nullptr)
{
mr_id = mr_tex->getID();
}
// get emissive texture
LLPointer<LLViewerFetchedTexture> emissive_tex = get_texture(folder, model_in, material_in.emissiveTexture.index);
LLUUID emissive_id;
if (emissive_tex != nullptr)
{
emissive_id = emissive_tex->getID();
}
// get normal map
LLPointer<LLViewerFetchedTexture> normal_tex = get_texture(folder, model_in, material_in.normalTexture.index);
LLUUID normal_id;
if (normal_tex != nullptr)
{
normal_id = normal_tex->getID();
}
mME->setAlbedoId(albedo_id);
mME->setMetallicRoughnessId(mr_id);
mME->setEmissiveId(emissive_id);
mME->setNormalId(normal_id);
mME->setAlphaMode(material_in.alphaMode);
mME->setAlphaCutoff(material_in.alphaCutoff);
mME->setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor));
mME->setEmissiveColor(get_color(material_in.emissiveFactor));
mME->setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor);
mME->setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor);
mME->setDoubleSided(material_in.doubleSided);
mME->openFloater();
}
void LLMaterialEditor::importMaterial()
{
(new LLMaterialFilePicker(this))->getFile();
}

View File

@ -33,26 +33,49 @@ class LLMaterialEditor : public LLFloater
public:
LLMaterialEditor(const LLSD& key);
// open a file dialog and select a gltf/glb file for import
void importMaterial();
void onClickSave();
// llpanel
BOOL postBuild() override;
LLUUID getAlbedoId();
void setAlbedoId(const LLUUID& id);
LLColor4 getAlbedoColor();
// sets both albedo color and transparency
void setAlbedoColor(const LLColor4& color);
F32 getTransparency();
std::string getAlphaMode();
void setAlphaMode(const std::string& alpha_mode);
F32 getAlphaCutoff();
void setAlphaCutoff(F32 alpha_cutoff);
LLUUID getMetallicRoughnessId();
void setMetallicRoughnessId(const LLUUID& id);
F32 getMetalnessFactor();
void setMetalnessFactor(F32 factor);
F32 getRoughnessFactor();
void setRoughnessFactor(F32 factor);
LLUUID getEmissiveId();
void setEmissiveId(const LLUUID& id);
LLColor4 getEmissiveColor();
void setEmissiveColor(const LLColor4& color);
LLUUID getNormalId();
void setNormalId(const LLUUID& id);
bool getDoubleSided();
void setDoubleSided(bool double_sided);
};

View File

@ -37,6 +37,7 @@
#include "llbuycurrencyhtml.h"
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
#include "llmaterialeditor.h"
#include "llfloatersnapshot.h"
#include "llfloateroutfitsnapshot.h"
#include "llimage.h"
@ -101,6 +102,20 @@ class LLFileEnableUploadModel : public view_listener_t
}
};
class LLFileEnableUploadMaterial : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::findInstance("material_editor");
if (me && me->isShown())
{
return false;
}
return true;
}
};
class LLMeshEnabled : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -282,6 +297,7 @@ static std::string SLOBJECT_EXTENSIONS = "slobject";
#endif
static std::string ALL_FILE_EXTENSIONS = "*.*";
static std::string MODEL_EXTENSIONS = "dae";
static std::string MATERIAL_EXTENSIONS = "gltf glb";
std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
{
@ -298,6 +314,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
return SLOBJECT_EXTENSIONS;
case LLFilePicker::FFLOAD_MODEL:
return MODEL_EXTENSIONS;
case LLFilePicker::FFLOAD_MATERIAL:
return MATERIAL_EXTENSIONS;
case LLFilePicker::FFLOAD_XML:
return XML_EXTENSIONS;
case LLFilePicker::FFLOAD_ALL:
@ -566,7 +584,20 @@ class LLFileUploadModel : public view_listener_t
return TRUE;
}
};
class LLFileUploadMaterial : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
if (me)
{
me->importMaterial();
}
return TRUE;
}
};
class LLFileUploadSound : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -1097,6 +1128,7 @@ void init_menu_file()
view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial");
view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");

View File

@ -1583,6 +1583,16 @@ function="World.EnvPreset"
<menu_item_call.on_visible
function="File.VisibleUploadModel"/>
</menu_item_call>
<menu_item_call
label="Material..."
layout="topleft"
name="Upload Material">
<menu_item_call.on_click
function="File.UploadMaterial"
parameter="" />
<menu_item_call.on_enable
function="File.EnableUploadMaterial" />
</menu_item_call>
<menu_item_call
label="Bulk..."
layout="topleft"