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
parent
ad533fcd6b
commit
f5d66e79ee
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue