summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-10-28 11:20:06 -0500
committerDave Parks <davep@lindenlab.com>2022-10-28 11:20:06 -0500
commit2752ab3b6212266047bd6b63b076d5be9b2a2d64 (patch)
treecfae87bddb01cdf623a54b2a27c78ab2801c4a56
parent81553613551ffc7c8253d67a3fb3a24137d19d51 (diff)
parent467c9f627c22dd88d9e9d058583b8279a2c5564e (diff)
Merge branch 'DRTVWR-559' of ssh://bitbucket.org/lindenlab/viewer into DRTVWR-559
-rw-r--r--indra/llprimitive/llgltfmaterial.cpp266
-rw-r--r--indra/llprimitive/llgltfmaterial.h8
-rw-r--r--indra/newview/llmaterialeditor.cpp190
-rw-r--r--indra/newview/lltexturectrl.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp30
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml1
7 files changed, 313 insertions, 188 deletions
diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp
index 7b6612b90a..6164234d6c 100644
--- a/indra/llprimitive/llgltfmaterial.cpp
+++ b/indra/llprimitive/llgltfmaterial.cpp
@@ -30,6 +30,11 @@
#include "tinygltf/tiny_gltf.h"
+const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
+
LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
{
*this = rhs;
@@ -82,6 +87,7 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const
{
#if 1
tinygltf::TinyGLTF gltf;
+
tinygltf::Model model_out;
std::ostringstream str;
@@ -105,118 +111,131 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
const tinygltf::Material& material_in = model.materials[mat_index];
- // get base color texture
- S32 tex_index = material_in.pbrMetallicRoughness.baseColorTexture.index;
- if (tex_index >= 0)
- {
- mBaseColorId.set(model.images[tex_index].uri);
- }
- else
+ // Apply base color texture
+ setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId);
+ // Apply normal map
+ setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId);
+ // Apply metallic-roughness texture
+ setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId);
+ // Apply emissive texture
+ setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId);
+
+ setAlphaMode(material_in.alphaMode);
+ mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f);
+
+ mBaseColor.set(material_in.pbrMetallicRoughness.baseColorFactor);
+ mEmissiveColor.set(material_in.emissiveFactor);
+
+ mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f);
+ mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f);
+
+ mDoubleSided = material_in.doubleSided;
+}
+
+LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value)
+{
+ const auto it = object.find(key);
+ if (it == object.end())
{
- mBaseColorId.setNull();
+ return default_value;
}
-
- // get normal map
- tex_index = material_in.normalTexture.index;
- if (tex_index >= 0)
+ const tinygltf::Value& vec2_json = std::get<1>(*it);
+ if (!vec2_json.IsArray() || vec2_json.ArrayLen() < LENGTHOFVECTOR2)
{
- mNormalId.set(model.images[tex_index].uri);
+ return default_value;
}
- else
+ LLVector2 value;
+ for (U32 i = 0; i < LENGTHOFVECTOR2; ++i)
{
- mNormalId.setNull();
+ const tinygltf::Value& real_json = vec2_json.Get(i);
+ if (!real_json.IsReal())
+ {
+ return default_value;
+ }
+ value.mV[i] = (F32)real_json.Get<double>();
}
+ return value;
+}
- // get metallic-roughness texture
- tex_index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index;
- if (tex_index >= 0)
+F32 float_from_json(const tinygltf::Value::Object& object, const char* key, const F32 default_value)
+{
+ const auto it = object.find(key);
+ if (it == object.end())
{
- mMetallicRoughnessId.set(model.images[tex_index].uri);
+ return default_value;
}
- else
+ const tinygltf::Value& real_json = std::get<1>(*it);
+ if (!real_json.IsReal())
{
- mMetallicRoughnessId.setNull();
+ return default_value;
}
+ return (F32)real_json.GetNumberAsDouble();
+}
- // get emissive texture
- tex_index = material_in.emissiveTexture.index;
- if (tex_index >= 0)
+template<typename T>
+std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info)
+{
+ const S32 texture_idx = texture_info.index;
+ if (texture_idx < 0 || texture_idx >= model.textures.size())
{
- mEmissiveId.set(model.images[tex_index].uri);
+ return "";
}
- else
+ const tinygltf::Texture& texture = model.textures[texture_idx];
+
+ // Ignore texture.sampler for now
+
+ const S32 image_idx = texture.source;
+ if (image_idx < 0 || image_idx >= model.images.size())
{
- mEmissiveId.setNull();
+ return "";
}
+ const tinygltf::Image& image = model.images[image_idx];
- setAlphaMode(material_in.alphaMode);
- mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f);
-
- mBaseColor.set(material_in.pbrMetallicRoughness.baseColorFactor);
- mEmissiveColor.set(material_in.emissiveFactor);
+ return image.uri;
+}
- mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f);
- mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f);
+// *NOTE: Use template here as workaround for the different similar texture info classes
+template<typename T>
+void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out)
+{
+ const std::string uri = gltf_get_texture_image(model, texture_info);
+ texture_id_out.set(uri);
- mDoubleSided = material_in.doubleSided;
+ const tinygltf::Value::Object& extensions_object = texture_info.extensions;
+ const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
+ if (transform_it != extensions_object.end())
+ {
+ const tinygltf::Value& transform_json = std::get<1>(*transform_it);
+ if (transform_json.IsObject())
+ {
+ const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>();
+ TextureTransform& transform = mTextureTransform[texture_info_id];
+ transform.mOffset = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset());
+ transform.mScale = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale());
+ transform.mRotation = float_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation());
+ }
+ }
}
void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
{
- if (model.materials.size() < mat_index + 1)
+ if (model.materials.size() < mat_index+1)
{
model.materials.resize(mat_index + 1);
}
tinygltf::Material& material_out = model.materials[mat_index];
- // set base color texture
- if (mBaseColorId.notNull())
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.pbrMetallicRoughness.baseColorTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mBaseColorId.asString();
- }
+ constexpr bool is_override = false;
+ // set base color texture
+ writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId, is_override, LLUUID());
// set normal texture
- if (mNormalId.notNull())
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.normalTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mNormalId.asString();
- }
-
+ writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId, is_override, LLUUID());
// set metallic-roughness texture
- if (mMetallicRoughnessId.notNull())
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.pbrMetallicRoughness.metallicRoughnessTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mMetallicRoughnessId.asString();
- }
-
+ writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId, is_override, LLUUID());
// set emissive texture
- if (mEmissiveId.notNull())
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.emissiveTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mEmissiveId.asString();
- }
+ writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId, is_override, LLUUID());
material_out.alphaMode = getAlphaMode();
material_out.alphaCutoff = mAlphaCutoff;
@@ -232,6 +251,46 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
model.asset.version = "2.0";
}
+template<typename T>
+void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const std::string& uri)
+{
+ const S32 image_idx = model.images.size();
+ model.images.emplace_back();
+ model.images[image_idx].uri = uri;
+
+ // The texture, not to be confused with the texture info
+ const S32 texture_idx = model.textures.size();
+ model.textures.emplace_back();
+ tinygltf::Texture& texture = model.textures[texture_idx];
+ texture.source = image_idx;
+
+ texture_info.index = texture_idx;
+}
+
+template<typename T>
+void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id, bool is_override, const LLUUID& base_texture_id) const
+{
+ if (texture_id.isNull() || (is_override && texture_id == base_texture_id))
+ {
+ return;
+ }
+
+ gltf_allocate_texture_image(model, texture_info, texture_id.asString());
+
+ tinygltf::Value::Object transform_map;
+ const TextureTransform& transform = mTextureTransform[texture_info_id];
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
+ tinygltf::Value(transform.mOffset.mV[VX]),
+ tinygltf::Value(transform.mOffset.mV[VY])
+ }));
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
+ tinygltf::Value(transform.mScale.mV[VX]),
+ tinygltf::Value(transform.mScale.mV[VY])
+ }));
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
+ texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
+}
+
void LLGLTFMaterial::setBaseColorId(const LLUUID& id)
{
@@ -390,53 +449,16 @@ void LLGLTFMaterial::writeOverridesToModel(tinygltf::Model& model, S32 mat_index
// TODO - fix handling of resetting to null/default values
- // set base color texture
- if (mBaseColorId.notNull() && mBaseColorId != base_material->mBaseColorId)
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.pbrMetallicRoughness.baseColorTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mBaseColorId.asString();
- }
+ constexpr bool is_override = true;
+ // set base color texture
+ writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId, is_override, base_material->mBaseColorId);
// set normal texture
- if (mNormalId.notNull() && mNormalId != base_material->mNormalId)
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.normalTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mNormalId.asString();
- }
-
+ writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId, is_override, base_material->mNormalId);
// set metallic-roughness texture
- if (mMetallicRoughnessId.notNull() && mMetallicRoughnessId != base_material->mMetallicRoughnessId)
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.pbrMetallicRoughness.metallicRoughnessTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mMetallicRoughnessId.asString();
- }
-
+ writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId, is_override, base_material->mMetallicRoughnessId);
// set emissive texture
- if (mEmissiveId.notNull() && mEmissiveId != base_material->mEmissiveId)
- {
- U32 idx = model.images.size();
- model.images.resize(idx + 1);
- model.textures.resize(idx + 1);
-
- material_out.emissiveTexture.index = idx;
- model.textures[idx].source = idx;
- model.images[idx].uri = mEmissiveId.asString();
- }
+ writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId, is_override, base_material->mEmissiveId);
if (mAlphaMode != base_material->mAlphaMode)
{
diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
index ea7e402805..b0afb11bb5 100644
--- a/indra/llprimitive/llgltfmaterial.h
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -118,6 +118,7 @@ public:
void setRoughnessFactor(F32 roughness);
void setAlphaMode(S32 mode);
void setDoubleSided(bool double_sided);
+
void setTextureOffset(TextureInfo texture_info, const LLVector2& offset);
void setTextureScale(TextureInfo texture_info, const LLVector2& scale);
void setTextureRotation(TextureInfo texture_info, float rotation);
@@ -189,5 +190,12 @@ public:
void applyOverride(const LLGLTFMaterial& override_mat);
+private:
+
+ template<typename T>
+ void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out);
+
+ template<typename T>
+ void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id, bool is_override, const LLUUID& base_texture_id) const;
};
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 7ffa767e37..1213deec64 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -67,7 +67,6 @@ const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
// Don't use ids here, LLPreview will attempt to use it as an inventory item
static const std::string LIVE_MATERIAL_EDITOR_KEY = "Live Editor";
-static const std::string SAVE_LIVE_MATERIAL_KEY = "Save Material Editor";
// Dirty flags
static const U32 MATERIAL_BASE_COLOR_DIRTY = 0x1 << 0;
@@ -228,6 +227,8 @@ LLMaterialEditor::LLMaterialEditor(const LLSD& key)
{
mAssetID = item->getAssetUUID();
}
+ // if this is a 'live editor' instance, it uses live overrides
+ mIsOverride = key.asString() == LIVE_MATERIAL_EDITOR_KEY;
}
void LLMaterialEditor::setObjectID(const LLUUID& object_id)
@@ -294,7 +295,7 @@ BOOL LLMaterialEditor::postBuild()
// Emissive
childSetCommitCallback("emissive color", changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY);
- childSetVisible("unsaved_changes", mUnsavedChanges);
+ childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
@@ -528,7 +529,8 @@ void LLMaterialEditor::resetUnsavedChanges()
void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
{
mUnsavedChanges |= dirty_flag;
- childSetVisible("unsaved_changes", mUnsavedChanges);
+ // at the moment live editing (mIsOverride) applies everything 'live'
+ childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
if (mUnsavedChanges)
{
@@ -852,17 +854,21 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)
}
else
{
- LL_WARNS() << "Failed to decode material asset: " << LL_ENDL;
- LL_WARNS() << warn_msg << LL_ENDL;
- LL_WARNS() << error_msg << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Floater " << getKey() << " Failed to decode material asset: " << LL_NEWLINE
+ << warn_msg << LL_NEWLINE
+ << error_msg << LL_ENDL;
}
}
}
}
+ else
+ {
+ LL_WARNS("MaterialEditor") << "Invalid LLSD content "<< asset << " for flaoter " << getKey() << LL_ENDL;
+ }
}
else
{
- LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Failed to deserialize material LLSD for flaoter " << getKey() << LL_ENDL;
}
return false;
@@ -1016,7 +1022,7 @@ bool LLMaterialEditor::saveIfNeeded()
std::string agent_url(region->getCapability("UpdateMaterialAgentInventory"));
if (agent_url.empty())
{
- LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL;
+ LL_ERRS("MaterialEditor") << "missing required agent inventory cap url" << LL_ENDL;
}
LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
}
@@ -1037,7 +1043,7 @@ bool LLMaterialEditor::saveToInventoryItem(const std::string &buffer, const LLUU
const LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
- LL_WARNS() << "Not connected to a region, cannot save material." << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Not connected to a region, cannot save material." << LL_ENDL;
return false;
}
std::string agent_url = region->getCapability("UpdateMaterialAgentInventory");
@@ -1078,7 +1084,7 @@ bool LLMaterialEditor::saveToInventoryItem(const std::string &buffer, const LLUU
}
else // !gAssetStorage
{
- LL_WARNS() << "Not connected to an materials capable region." << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Not connected to an materials capable region." << LL_ENDL;
return false;
}
@@ -1165,7 +1171,7 @@ void LLMaterialEditor::finishSaveAs(
else if (me)
{
me->setEnabled(true);
- LL_WARNS() << "Item does not exist" << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Item does not exist, floater " << me->getKey() << LL_ENDL;
}
}
@@ -1175,8 +1181,10 @@ void LLMaterialEditor::refreshFromInventory(const LLUUID& new_item_id)
{
// refreshFromInventory shouldn't be called for overrides,
// but just in case.
+ LL_WARNS("MaterialEditor") << "Tried to refresh from inventory for live editor" << LL_ENDL;
return;
}
+ LLSD old_key = getKey();
if (new_item_id.notNull())
{
mItemUUID = new_item_id;
@@ -1199,7 +1207,7 @@ void LLMaterialEditor::refreshFromInventory(const LLUUID& new_item_id)
setKey(LLSD(new_item_id));
}
}
- LL_DEBUGS() << "LLPreviewNotecard::refreshFromInventory()" << LL_ENDL;
+ LL_DEBUGS("MaterialEditor") << "New floater key: " << getKey() << " Old key: " << old_key << LL_ENDL;
loadAsset();
}
@@ -1390,7 +1398,7 @@ static void pack_textures(
if (base_color_img)
{
base_color_j2c = LLViewerTextureList::convertToUploadFile(base_color_img);
- LL_INFOS() << "BaseColor: " << base_color_j2c->getDataSize() << LL_ENDL;
+ LL_DEBUGS("MaterialEditor") << "BaseColor: " << base_color_j2c->getDataSize() << LL_ENDL;
}
if (normal_img)
@@ -1403,7 +1411,7 @@ static void pack_textures(
S32 lossy_bytes = normal_j2c->getDataSize();
S32 lossless_bytes = test->getDataSize();
- LL_INFOS() << llformat("Lossless vs Lossy: (%d/%d) = %.2f", lossless_bytes, lossy_bytes, (F32)lossless_bytes / lossy_bytes) << LL_ENDL;
+ LL_DEBUGS("MaterialEditor") << llformat("Lossless vs Lossy: (%d/%d) = %.2f", lossless_bytes, lossy_bytes, (F32)lossless_bytes / lossy_bytes) << LL_ENDL;
normal_j2c = test;
}
@@ -1411,13 +1419,13 @@ static void pack_textures(
if (mr_img)
{
mr_j2c = LLViewerTextureList::convertToUploadFile(mr_img);
- LL_INFOS() << "Metallic/Roughness: " << mr_j2c->getDataSize() << LL_ENDL;
+ LL_DEBUGS("MaterialEditor") << "Metallic/Roughness: " << mr_j2c->getDataSize() << LL_ENDL;
}
if (emissive_img)
{
emissive_j2c = LLViewerTextureList::convertToUploadFile(emissive_img);
- LL_INFOS() << "Emissive: " << emissive_j2c->getDataSize() << LL_ENDL;
+ LL_DEBUGS("MaterialEditor") << "Emissive: " << emissive_j2c->getDataSize() << LL_ENDL;
}
}
@@ -1507,10 +1515,12 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind
}
void LLMaterialEditor::onSelectionChanged()
{
+ // This won't get deletion or deselectAll()
+ // Might need to handle that separately
mUnsavedChanges = 0;
clearTextures();
setFromSelection();
- saveLiveValues();
+ // saveLiveValues(); todo
}
void LLMaterialEditor::saveLiveValues()
@@ -1532,6 +1542,8 @@ void LLMaterialEditor::saveLiveValues()
S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
for (U8 te = 0; te < num_tes; te++)
{
+ // Todo: fix this, overrides don't care about ids,
+ // we will have to save actual values or materials
LLUUID mat_id = objectp->getRenderMaterialID(te);
mEditor->mObjectOverridesSavedValues[local_id].push_back(mat_id);
}
@@ -1544,11 +1556,11 @@ void LLMaterialEditor::saveLiveValues()
void LLMaterialEditor::loadLive()
{
+ // Allow only one 'live' instance
const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", floater_key);
if (me)
{
- me->mIsOverride = true;
me->setFromSelection();
me->setTitle(me->getString("material_override_title"));
me->childSetVisible("save", false);
@@ -1569,13 +1581,13 @@ void LLMaterialEditor::loadLive()
void LLMaterialEditor::loadObjectSave()
{
- const LLSD floater_key(SAVE_LIVE_MATERIAL_KEY);
- LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", floater_key);
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
if (me && me->setFromSelection())
{
- me->mIsOverride = false;
me->childSetVisible("save", false);
- me->openFloater(floater_key);
+ me->mMaterialName = LLTrans::getString("New Material");
+ me->setTitle(me->mMaterialName);
+ me->openFloater();
me->setFocus(TRUE);
}
}
@@ -1584,7 +1596,7 @@ void LLMaterialEditor::loadFromGLTFMaterial(LLUUID &asset_id)
{
if (asset_id.isNull())
{
- LL_WARNS() << "Trying to open material with null id" << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Trying to open material with null id" << LL_ENDL;
return;
}
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
@@ -2053,13 +2065,15 @@ public:
if (material.isNull())
{
- material = new LLGLTFMaterial();
- }
- else
- {
- material = new LLGLTFMaterial(*material);
+ // overrides are not supposed to work or apply if
+ // there is no base material to work from
+ return false;
}
+ // make a copy to not invalidate existing
+ // material for multiple objects
+ material = new LLGLTFMaterial(*material);
+
// Override object's values with values from editor where appropriate
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_DIRTY)
{
@@ -2153,7 +2167,7 @@ void LLMaterialEditor::applyToSelection()
}
else
{
- LL_WARNS() << "not connected to materials capable region, missing ModifyMaterialParams cap" << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Not connected to materials capable region, missing ModifyMaterialParams cap" << LL_ENDL;
// Fallback local preview. Will be removed once override systems is finished and new cap is deployed everywhere.
LLPointer<LLFetchedGLTFMaterial> mat = new LLFetchedGLTFMaterial();
@@ -2206,45 +2220,114 @@ void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)
bool LLMaterialEditor::setFromSelection()
{
- struct LLSelectedTEGetGLTFRenderMaterial : public LLSelectedTEGetFunctor<LLPointer<LLGLTFMaterial> >
+ struct LLSelectedTEGetmatIdAndPermissions : public LLSelectedTEFunctor
{
- LLPointer<LLGLTFMaterial> get(LLViewerObject* objectp, S32 te_index)
+ LLSelectedTEGetmatIdAndPermissions(bool for_override)
+ : mIsOverride(for_override)
+ , mIdenticalTexColor(true)
+ , mIdenticalTexMetal(true)
+ , mIdenticalTexEmissive(true)
+ , mIdenticalTexNormal(true)
+ , mFirst(true)
+ {}
+
+ bool apply(LLViewerObject* objectp, S32 te_index)
{
if (!objectp)
{
- return nullptr;
+ return false;
}
+ LLUUID mat_id = objectp->getRenderMaterialID(te_index);
+ bool can_use = mIsOverride ? objectp->permModify() : objectp->permCopy();
LLTextureEntry *tep = objectp->getTE(te_index);
- if (!tep)
+ // We might want to disable this entirely if at least
+ // something in selection is no-copy or no modify
+ // or has no base material
+ if (can_use && tep && mat_id.notNull())
{
- return nullptr;
+ LLPointer<LLGLTFMaterial> mat = tep->getGLTFRenderMaterial();
+ LLUUID tex_color_id;
+ LLUUID tex_metal_id;
+ LLUUID tex_emissive_id;
+ LLUUID tex_normal_id;
+ llassert(mat.notNull()); // by this point shouldn't be null
+ if (mat.notNull())
+ {
+ tex_color_id = mat->mBaseColorId;
+ tex_metal_id = mat->mMetallicRoughnessId;
+ tex_emissive_id = mat->mEmissiveId;
+ tex_normal_id = mat->mNormalId;
+ }
+ if (mFirst)
+ {
+ mMaterial = mat;
+ mTexColorId = tex_color_id;
+ mTexMetalId = tex_metal_id;
+ mTexEmissiveId = tex_emissive_id;
+ mTexNormalId = tex_normal_id;
+ mFirst = false;
+ }
+ else
+ {
+ if (mTexColorId != tex_color_id)
+ {
+ mIdenticalTexColor = false;
+ }
+ if (mTexMetalId != tex_metal_id)
+ {
+ mIdenticalTexMetal = false;
+ }
+ if (mTexEmissiveId != tex_emissive_id)
+ {
+ mIdenticalTexEmissive = false;
+ }
+ if (mTexNormalId != tex_normal_id)
+ {
+ mIdenticalTexNormal = false;
+ }
+ }
}
- return tep->getGLTFRenderMaterial(); // present user with combined override + asset
+ return true;
}
- } func;
-
- LLPointer<LLGLTFMaterial> mat;
- bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat);
- if (mat.notNull())
- {
- setFromGLTFMaterial(mat);
+ bool mIsOverride;
+ bool mIdenticalTexColor;
+ bool mIdenticalTexMetal;
+ bool mIdenticalTexEmissive;
+ bool mIdenticalTexNormal;
+ bool mFirst;
+ LLUUID mTexColorId;
+ LLUUID mTexMetalId;
+ LLUUID mTexEmissiveId;
+ LLUUID mTexNormalId;
+ LLPointer<LLGLTFMaterial> mMaterial;
+ } func(mIsOverride);
+
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ if (func.mMaterial.notNull())
+ {
+ setFromGLTFMaterial(func.mMaterial);
+ setEnableEditing(true);
}
else
{
// pick defaults from a blank material;
LLGLTFMaterial blank_mat;
setFromGLTFMaterial(&blank_mat);
+ if (mIsOverride)
+ {
+ setEnableEditing(false);
+ }
}
if (mIsOverride)
{
- mBaseColorTextureCtrl->setTentative(!identical);
- mMetallicTextureCtrl->setTentative(!identical);
- mEmissiveTextureCtrl->setTentative(!identical);
- mNormalTextureCtrl->setTentative(!identical);
+ mBaseColorTextureCtrl->setTentative(!func.mIdenticalTexColor);
+ mMetallicTextureCtrl->setTentative(!func.mIdenticalTexMetal);
+ mEmissiveTextureCtrl->setTentative(!func.mIdenticalTexEmissive);
+ mNormalTextureCtrl->setTentative(!func.mIdenticalTexNormal);
}
- return mat.notNull();
+ return func.mMaterial.notNull();
}
@@ -2279,6 +2362,7 @@ void LLMaterialEditor::loadAsset()
{
mAssetID = item->getAssetUUID();
+
if (mAssetID.isNull())
{
mAssetStatus = PREVIEW_ASSET_LOADED;
@@ -2305,7 +2389,7 @@ void LLMaterialEditor::loadAsset()
else
{
// The object that we're trying to look at disappeared, bail.
- LL_WARNS() << "Can't find object " << mObjectUUID << " associated with notecard." << LL_ENDL;
+ LL_WARNS("MaterialEditor") << "Can't find object " << mObjectUUID << " associated with material." << LL_ENDL;
mAssetID.setNull();
mAssetStatus = PREVIEW_ASSET_LOADED;
resetUnsavedChanges();
@@ -2376,11 +2460,15 @@ void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
- LL_INFOS() << "LLMaterialEditor::onLoadComplete()" << LL_ENDL;
LLSD* floater_key = (LLSD*)user_data;
+ LL_DEBUGS("MaterialEditor") << "loading " << asset_uuid << " for " << *floater_key << LL_ENDL;
LLMaterialEditor* editor = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", *floater_key);
if (editor)
{
+ if (asset_uuid != editor->mAssetID)
+ {
+ LL_WARNS() << "Asset id mismatch, expected: " << editor->mAssetID << " got: " << asset_uuid << LL_ENDL;
+ }
if (0 == status)
{
LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
@@ -2420,6 +2508,10 @@ void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid,
editor->mAssetStatus = PREVIEW_ASSET_ERROR;
}
}
+ else
+ {
+ LL_DEBUGS("MaterialEditor") << "Floater " << *floater_key << " does not exist." << LL_ENDL;
+ }
delete floater_key;
}
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 5d9eb48e6c..ebb7ee609c 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -533,7 +533,7 @@ void LLFloaterTexturePicker::draw()
}
getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
- getChildView("Blank")->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID != mDefaultImageAssetID) || mTentative);
+ getChildView("Blank")->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative);
getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
LLFloater::draw();
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index e1b92e5f2e..3161579482 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2809,37 +2809,39 @@ void handle_object_open()
LLFloaterReg::showInstance("openobject");
}
-struct LLSelectedTEGetmatIdAndPermissions : public LLSelectedTEGetFunctor<LLUUID>
+struct LLSelectedTEGetmatIdAndPermissions : public LLSelectedTEFunctor
{
LLSelectedTEGetmatIdAndPermissions() : mCanCopy(true), mCanModify(true), mCanTransfer(true) {}
- LLUUID get(LLViewerObject* object, S32 te_index)
+ bool apply(LLViewerObject* objectp, S32 te_index)
{
- mCanCopy &= (bool)object->permCopy();
- mCanTransfer &= (bool)object->permTransfer();
- mCanModify &= (bool)object->permModify();
- // return true if all ids are identical
- return object->getRenderMaterialID(te_index);
+ mCanCopy &= (bool)objectp->permCopy();
+ mCanTransfer &= (bool)objectp->permTransfer();
+ mCanModify &= (bool)objectp->permModify();
+ LLUUID mat_id = objectp->getRenderMaterialID(te_index);
+ if (mat_id.notNull())
+ {
+ mMaterialId = mat_id;
+ }
+ return true;
}
bool mCanCopy;
bool mCanModify;
bool mCanTransfer;
+ LLUUID mMaterialId;
};
bool enable_object_edit_gltf_material()
{
LLSelectedTEGetmatIdAndPermissions func;
- LLUUID mat_id;
- LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat_id);
-
- return func.mCanModify;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ return func.mCanModify && func.mMaterialId.notNull();
}
bool enable_object_save_gltf_material()
{
LLSelectedTEGetmatIdAndPermissions func;
- LLUUID mat_id;
- LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat_id);
- return func.mCanCopy && mat_id.notNull();
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ return func.mCanCopy && func.mMaterialId.notNull();
}
bool enable_object_open()
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 434123faf0..84264cd2e6 100644
--- a/indra/newview/skins/default/xui/en/floater_material_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -15,7 +15,7 @@
<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>
- <string name="material_override_title">Material override</string>
+ <string name="material_override_title">Editing Material</string>
<scroll_container
name="materials_scroll"
@@ -475,7 +475,7 @@
left="10"
top="0"
>
- Usaved changes
+ Unsaved changes
</text>
<button
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index 104bcb9257..ff2323784c 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -252,6 +252,7 @@
width="64" />
<texture_picker
can_apply_immediately="true"
+ allow_no_texture="true"
follows="left|top"
height="80"
label="PBR "