diff options
author | Brad Kittenbrink <brad@lindenlab.com> | 2022-06-27 10:24:53 -0700 |
---|---|---|
committer | Brad Kittenbrink <brad@lindenlab.com> | 2022-06-27 10:24:53 -0700 |
commit | acdd77d4ce31a5014eff72f18b374e877001adf9 (patch) | |
tree | 2345c2ac7b2e1c8c1b341ccf6ff1e65993d8dea3 /indra/newview/llmaterialeditor.cpp | |
parent | fbb6eb216f5dc06ff5c7c1cabc6ab46a94918e1b (diff) | |
parent | 231c618a844cee26a3779b703c88d8807df872e6 (diff) |
Merge remote-tracking branch 'origin/DRTVWR-559' into brad/SL-17602-new-material-upload
Diffstat (limited to 'indra/newview/llmaterialeditor.cpp')
-rw-r--r-- | indra/newview/llmaterialeditor.cpp | 399 |
1 files changed, 360 insertions, 39 deletions
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 828b368063..1744bf9033 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -29,17 +29,20 @@ #include "llmaterialeditor.h" #include "llagent.h" +#include "llappviewer.h" #include "llcombobox.h" #include "llinventorymodel.h" +#include "llnotificationsutil.h" +#include "lltexturectrl.h" +#include "lltrans.h" #include "llviewermenufile.h" -#include "llappviewer.h" #include "llviewertexture.h" -#include "llnotificationsutil.h" #include "llsdutil.h" #include "llselectmgr.h" #include "llviewerinventory.h" #include "llviewerregion.h" #include "llvovolume.h" +#include "llcolorswatch.h" #include "tinygltf/tiny_gltf.h" @@ -50,23 +53,84 @@ // Default constructor LLMaterialEditor::LLMaterialEditor(const LLSD& key) : LLFloater(key) + , mHasUnsavedChanges(false) { } BOOL LLMaterialEditor::postBuild() { + mAlbedoTextureCtrl = getChild<LLTextureCtrl>("albedo_texture"); + mMetallicTextureCtrl = getChild<LLTextureCtrl>("metallic_roughness_texture"); + mEmissiveTextureCtrl = getChild<LLTextureCtrl>("emissive_texture"); + mNormalTextureCtrl = getChild<LLTextureCtrl>("normal_texture"); + + mAlbedoTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitAlbedoTexture, this, _1, _2)); + mMetallicTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitMetallicTexture, this, _1, _2)); + mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitEmissiveTexture, this, _1, _2)); + mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitNormalTexture, this, _1, _2)); + childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this)); + childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this)); + childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this)); + + boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void*) { setHasUnsavedChanges(true); }; + + childSetCommitCallback("double sided", changes_callback, NULL); + + // Albedo + childSetCommitCallback("albedo color", changes_callback, NULL); + getChild<LLColorSwatchCtrl>("albedo color")->setCanApplyImmediately(TRUE); + childSetCommitCallback("transparency", changes_callback, NULL); + childSetCommitCallback("alpha mode", changes_callback, NULL); + childSetCommitCallback("alpha cutoff", changes_callback, NULL); + + // Metallic-Roughness + childSetCommitCallback("metalness factor", changes_callback, NULL); + childSetCommitCallback("roughness factor", changes_callback, NULL); + + // Metallic-Roughness + childSetCommitCallback("metalness factor", changes_callback, NULL); + childSetCommitCallback("roughness factor", changes_callback, NULL); + + // Emissive + childSetCommitCallback("emissive color", changes_callback, NULL); + getChild<LLColorSwatchCtrl>("emissive color")->setCanApplyImmediately(TRUE); + + childSetVisible("unsaved_changes", mHasUnsavedChanges); + return LLFloater::postBuild(); } +void LLMaterialEditor::onClickCloseBtn(bool app_quitting) +{ + if (app_quitting) + { + closeFloater(app_quitting); + } + else + { + onClickCancel(); + } +} + LLUUID LLMaterialEditor::getAlbedoId() { - return childGetValue("albedo texture").asUUID(); + return mAlbedoTextureCtrl->getValue().asUUID(); } void LLMaterialEditor::setAlbedoId(const LLUUID& id) { - childSetValue("albedo texture", id); + mAlbedoTextureCtrl->setValue(id); + mAlbedoTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("albedo_upload_fee", getString("upload_fee_string")); + // Only set if we will need to upload this texture + mAlbedoTextureUploadId = id; + } } LLColor4 LLMaterialEditor::getAlbedoColor() @@ -76,7 +140,6 @@ LLColor4 LLMaterialEditor::getAlbedoColor() return ret; } - void LLMaterialEditor::setAlbedoColor(const LLColor4& color) { childSetValue("albedo color", color.getValue()); @@ -108,14 +171,29 @@ void LLMaterialEditor::setAlphaCutoff(F32 alpha_cutoff) childSetValue("alpha cutoff", alpha_cutoff); } +void LLMaterialEditor::setMaterialName(const std::string &name) +{ + setTitle(name); + mMaterialName = name; +} + LLUUID LLMaterialEditor::getMetallicRoughnessId() { - return childGetValue("metallic-roughness texture").asUUID(); + return mMetallicTextureCtrl->getValue().asUUID(); } void LLMaterialEditor::setMetallicRoughnessId(const LLUUID& id) { - childSetValue("metallic-roughness texture", id); + mMetallicTextureCtrl->setValue(id); + mMetallicTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("metallic_upload_fee", getString("upload_fee_string")); + mMetallicTextureUploadId = id; + } } F32 LLMaterialEditor::getMetalnessFactor() @@ -140,12 +218,21 @@ void LLMaterialEditor::setRoughnessFactor(F32 factor) LLUUID LLMaterialEditor::getEmissiveId() { - return childGetValue("emissive texture").asUUID(); + return mEmissiveTextureCtrl->getValue().asUUID(); } void LLMaterialEditor::setEmissiveId(const LLUUID& id) { - childSetValue("emissive texture", id); + mEmissiveTextureCtrl->setValue(id); + mEmissiveTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("emissive_upload_fee", getString("upload_fee_string")); + mEmissiveTextureUploadId = id; + } } LLColor4 LLMaterialEditor::getEmissiveColor() @@ -160,12 +247,21 @@ void LLMaterialEditor::setEmissiveColor(const LLColor4& color) LLUUID LLMaterialEditor::getNormalId() { - return childGetValue("normal texture").asUUID(); + return mNormalTextureCtrl->getValue().asUUID(); } void LLMaterialEditor::setNormalId(const LLUUID& id) { - childSetValue("normal texture", id); + mNormalTextureCtrl->setValue(id); + mNormalTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("normal_upload_fee", getString("upload_fee_string")); + mNormalTextureUploadId = id; + } } bool LLMaterialEditor::getDoubleSided() @@ -178,6 +274,76 @@ void LLMaterialEditor::setDoubleSided(bool double_sided) childSetValue("double sided", double_sided); } +void LLMaterialEditor::setHasUnsavedChanges(bool value) +{ + if (value != mHasUnsavedChanges) + { + mHasUnsavedChanges = value; + childSetVisible("unsaved_changes", value); + } + + // HACK -- apply any changes to selection immediately + applyToSelection(); +} + +void LLMaterialEditor::onCommitAlbedoTexture(LLUICtrl * ctrl, const LLSD & data) +{ + // might be better to use arrays, to have a single callback + // and not to repeat the same thing for each tecture control + LLUUID new_val = mAlbedoTextureCtrl->getValue().asUUID(); + if (new_val == mAlbedoTextureUploadId && mAlbedoTextureUploadId.notNull()) + { + childSetValue("albedo_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("albedo_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID(); + if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull()) + { + childSetValue("metallic_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("metallic_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID(); + if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull()) + { + childSetValue("emissive_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("emissive_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mNormalTextureCtrl->getValue().asUUID(); + if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull()) + { + childSetValue("normal_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("normal_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + static void write_color(const LLColor4& color, std::vector<double>& c) { @@ -272,7 +438,7 @@ void LLMaterialEditor::onClickSave() std::string dump = str.str(); - LL_INFOS() << dump << LL_ENDL; + LL_INFOS() << mMaterialName << ": " << dump << LL_ENDL; // gen a new uuid for this asset LLTransactionID tid; @@ -313,6 +479,54 @@ void LLMaterialEditor::onClickSave() ); } +void LLMaterialEditor::onClickSaveAs() +{ + LLSD args; + args["DESC"] = mMaterialName; + + LLNotificationsUtil::add("SaveMaterialAs", args, LLSD(), boost::bind(&LLMaterialEditor::onSaveAsMsgCallback, this, _1, _2)); +} + +void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + std::string new_name = response["message"].asString(); + LLStringUtil::trim(new_name); + if (!new_name.empty()) + { + setMaterialName(new_name); + onClickSave(); + } + else + { + LLNotificationsUtil::add("InvalidMaterialName"); + } + } +} + +void LLMaterialEditor::onClickCancel() +{ + if (mHasUnsavedChanges) + { + LLNotificationsUtil::add("UsavedMaterialChanges", LLSD(), LLSD(), boost::bind(&LLMaterialEditor::onCancelMsgCallback, this, _1, _2)); + } + else + { + closeFloater(); + } +} + +void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + closeFloater(); + } +} + class LLMaterialFilePicker : public LLFilePickerThread { public: @@ -358,28 +572,115 @@ const tinygltf::Image* get_image_from_texture_index(const tinygltf::Model& model return nullptr; } -static LLViewerFetchedTexture* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index) +static LLImageRaw* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index) { - LLViewerFetchedTexture* ret = nullptr; - const tinygltf::Image* image = get_image_from_texture_index(model, texture_index); + LLImageRaw* rawImage = nullptr; + if (image != nullptr && image->bits == 8 && !image->image.empty() && image->component <= 4) { - LLPointer<LLImageRaw> rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); + rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); rawImage->verticalFlip(); - - ret = LLViewerTextureManager::getFetchedTexture(rawImage, FTType::FTT_LOCAL_FILE, true); + } + + return rawImage; +} - ret->forceToSaveRawImage(0, F32_MAX); +static void strip_alpha_channel(LLPointer<LLImageRaw>& img) +{ + if (img->getComponents() == 4) + { + LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3); + tmp->copyUnscaled4onto3(img); + img = tmp; } +} - // TODO: provide helpful error message if image fails to load +// copy red channel from src_img to dst_img +// PRECONDITIONS: +// dst_img must be 3 component +// src_img and dst_image must have the same dimensions +static void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img) +{ + llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight()); + llassert(dst_img->getComponents() == 3); - return ret; + U32 pixel_count = dst_img->getWidth() * dst_img->getHeight(); + U8* src = src_img->getData(); + U8* dst = dst_img->getData(); + S8 src_components = src_img->getComponents(); + + for (U32 i = 0; i < pixel_count; ++i) + { + dst[i * 3] = src[i * src_components]; + } +} + +static void pack_textures(tinygltf::Model& model, tinygltf::Material& material, + LLPointer<LLImageRaw>& albedo_img, + LLPointer<LLImageRaw>& normal_img, + LLPointer<LLImageRaw>& mr_img, + LLPointer<LLImageRaw>& emissive_img, + LLPointer<LLImageRaw>& occlusion_img, + LLPointer<LLViewerFetchedTexture>& albedo_tex, + LLPointer<LLViewerFetchedTexture>& normal_tex, + LLPointer<LLViewerFetchedTexture>& mr_tex, + LLPointer<LLViewerFetchedTexture>& emissive_tex) +{ + // TODO: downscale if needed + if (albedo_img) + { + albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true); + } + + if (normal_img) + { + strip_alpha_channel(normal_img); + normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true); + } + + if (mr_img) + { + strip_alpha_channel(mr_img); + + if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) + { + // occlusion is a distinct texture from pbrMetallicRoughness + // pack into mr red channel + int occlusion_idx = material.occlusionTexture.index; + int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; + if (occlusion_idx != mr_idx) + { + //scale occlusion image to match resolution of mr image + occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); + + copy_red_channel(occlusion_img, mr_img); + } + } + } + else if (occlusion_img) + { + //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over + mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3); + mr_img->clear(255, 255, 255); + copy_red_channel(occlusion_img, mr_img); + + } + + if (mr_img) + { + mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true); + } + + if (emissive_img) + { + strip_alpha_channel(emissive_img); + emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true); + } } static LLColor4 get_color(const std::vector<double>& in) @@ -423,13 +724,14 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename) if (!loaded) { - // TODO: show error_msg to user + LLNotificationsUtil::add("CannotUploadMaterial"); return; } if (model_in.materials.empty()) { - // TODO: show error message that materials are missing + // materials are missing + LLNotificationsUtil::add("CannotUploadMaterial"); return; } @@ -443,41 +745,56 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename) model_out.materials.resize(1); // get albedo texture - LLPointer<LLViewerFetchedTexture> albedo_tex = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); + LLPointer<LLImageRaw> albedo_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); + // get normal map + LLPointer<LLImageRaw> normal_img = get_texture(folder, model_in, material_in.normalTexture.index); + // get metallic-roughness texture + LLPointer<LLImageRaw> mr_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); + // get emissive texture + LLPointer<LLImageRaw> emissive_img = get_texture(folder, model_in, material_in.emissiveTexture.index); + // get occlusion map if needed + LLPointer<LLImageRaw> occlusion_img; + if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) + { + occlusion_img = get_texture(folder, model_in, material_in.occlusionTexture.index); + } + LLPointer<LLViewerFetchedTexture> albedo_tex; + LLPointer<LLViewerFetchedTexture> normal_tex; + LLPointer<LLViewerFetchedTexture> mr_tex; + LLPointer<LLViewerFetchedTexture> emissive_tex; + + pack_textures(model_in, material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img, + albedo_tex, normal_tex, mr_tex, emissive_tex); + LLUUID albedo_id; if (albedo_tex != nullptr) { + albedo_tex->forceToSaveRawImage(0, F32_MAX); albedo_id = albedo_tex->getID(); } - // get metallic-roughness texture - LLPointer<LLViewerFetchedTexture> mr_tex = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); + LLUUID normal_id; + if (normal_tex != nullptr) + { + normal_tex->forceToSaveRawImage(0, F32_MAX); + normal_id = normal_tex->getID(); + } LLUUID mr_id; if (mr_tex != nullptr) { + mr_tex->forceToSaveRawImage(0, F32_MAX); 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_tex->forceToSaveRawImage(0, F32_MAX); 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); @@ -491,9 +808,13 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename) mME->setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor); mME->setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor); - + mME->setDoubleSided(material_in.doubleSided); + std::string new_material = LLTrans::getString("New Material"); + mME->setMaterialName(new_material); + + mME->setHasUnsavedChanges(true); mME->openFloater(); mME->applyToSelection(); |