master
Ansariel 2022-11-02 12:30:32 +01:00
commit 6af68b852c
16 changed files with 980 additions and 892 deletions

View File

@ -28,6 +28,7 @@
#include "llgltfmaterial.h"
// NOTE -- this should be the one and only place tiny_gltf.h is included
#include "tinygltf/tiny_gltf.h"
const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
@ -35,6 +36,9 @@ const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
// special UUID that indicates a null UUID in override data
static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
{
*this = rhs;
@ -42,6 +46,7 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
{
LL_PROFILE_ZONE_SCOPED;
//have to do a manual operator= because of LLRefCount
mBaseColorId = rhs.mBaseColorId;
mNormalId = rhs.mNormalId;
@ -65,7 +70,7 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg)
{
#if 1
LL_PROFILE_ZONE_SCOPED;
tinygltf::TinyGLTF gltf;
tinygltf::Model model_in;
@ -74,18 +79,14 @@ bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, st
{
setFromModel(model_in, 0);
//DEBUG generate json and print
LL_INFOS() << asJSON(true) << LL_ENDL;
return true;
}
#endif
return false;
}
std::string LLGLTFMaterial::asJSON(bool prettyprint) const
{
#if 1
LL_PROFILE_ZONE_SCOPED;
tinygltf::TinyGLTF gltf;
tinygltf::Model model_out;
@ -97,13 +98,11 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const
gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false);
return str.str();
#else
return "";
#endif
}
void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
{
LL_PROFILE_ZONE_SCOPED;
if (model.materials.size() <= mat_index)
{
return;
@ -198,6 +197,7 @@ std::string gltf_get_texture_image(const tinygltf::Model& model, const T& textur
template<typename T>
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out)
{
LL_PROFILE_ZONE_SCOPED;
const std::string uri = gltf_get_texture_image(model, texture_info);
texture_id_out.set(uri);
@ -219,6 +219,7 @@ void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& textu
void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
{
LL_PROFILE_ZONE_SCOPED;
if (model.materials.size() < mat_index+1)
{
model.materials.resize(mat_index + 1);
@ -277,6 +278,7 @@ void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const
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
{
LL_PROFILE_ZONE_SCOPED;
if (texture_id.isNull() || (is_override && texture_id == base_texture_id))
{
return;
@ -298,64 +300,144 @@ void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, Tex
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
}
// static
void LLGLTFMaterial::hackOverrideUUID(LLUUID& id)
{
if (id == LLUUID::null)
{
id = GLTF_OVERRIDE_NULL_UUID;
}
}
void LLGLTFMaterial::setBaseColorId(const LLUUID& id)
void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override)
{
mBaseColorId = id;
if (for_override)
{
hackOverrideUUID(mBaseColorId);
}
}
void LLGLTFMaterial::setNormalId(const LLUUID& id)
void LLGLTFMaterial::setNormalId(const LLUUID& id, bool for_override)
{
mNormalId = id;
if (for_override)
{
hackOverrideUUID(mNormalId);
}
}
void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id)
void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id, bool for_override)
{
mMetallicRoughnessId = id;
if (for_override)
{
hackOverrideUUID(mMetallicRoughnessId);
}
}
void LLGLTFMaterial::setEmissiveId(const LLUUID& id)
void LLGLTFMaterial::setEmissiveId(const LLUUID& id, bool for_override)
{
mEmissiveId = id;
if (for_override)
{
hackOverrideUUID(mEmissiveId);
}
}
void LLGLTFMaterial::setBaseColorFactor(const LLColor3& baseColor, F32 transparency)
void LLGLTFMaterial::setBaseColorFactor(const LLColor4& baseColor, bool for_override)
{
mBaseColor.set(baseColor, transparency);
mBaseColor.set(baseColor);
mBaseColor.clamp();
if (for_override)
{ // hack -- nudge off of default value
if (mBaseColor == getDefaultBaseColor())
{
mBaseColor.mV[3] -= FLT_EPSILON;
}
}
}
void LLGLTFMaterial::setAlphaCutoff(F32 cutoff)
void LLGLTFMaterial::setAlphaCutoff(F32 cutoff, bool for_override)
{
mAlphaCutoff = llclamp(cutoff, 0.f, 1.f);
if (for_override)
{ // hack -- nudge off of default value
if (mAlphaCutoff == getDefaultAlphaCutoff())
{
mAlphaCutoff -= FLT_EPSILON;
}
}
}
void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor)
void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override)
{
mEmissiveColor = emissiveColor;
mEmissiveColor.clamp();
if (for_override)
{ // hack -- nudge off of default value
if (mEmissiveColor == getDefaultEmissiveColor())
{
mEmissiveColor.mV[0] += FLT_EPSILON;
}
}
}
void LLGLTFMaterial::setMetallicFactor(F32 metallic)
void LLGLTFMaterial::setMetallicFactor(F32 metallic, bool for_override)
{
mMetallicFactor = llclamp(metallic, 0.f, 1.f);
mMetallicFactor = llclamp(metallic, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f);
}
void LLGLTFMaterial::setRoughnessFactor(F32 roughness)
void LLGLTFMaterial::setRoughnessFactor(F32 roughness, bool for_override)
{
mRoughnessFactor = llclamp(roughness, 0.f, 1.f);
mRoughnessFactor = llclamp(roughness, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f);
}
void LLGLTFMaterial::setAlphaMode(S32 mode)
void LLGLTFMaterial::setAlphaMode(const std::string& mode, bool for_override)
{
S32 m = getDefaultAlphaMode();
if (mode == "MASK")
{
m = ALPHA_MODE_MASK;
}
else if (mode == "BLEND")
{
m = ALPHA_MODE_BLEND;
}
setAlphaMode(m, for_override);
}
const char* LLGLTFMaterial::getAlphaMode() const
{
switch (mAlphaMode)
{
case ALPHA_MODE_MASK: return "MASK";
case ALPHA_MODE_BLEND: return "BLEND";
default: return "OPAQUE";
}
}
void LLGLTFMaterial::setAlphaMode(S32 mode, bool for_override)
{
mAlphaMode = (AlphaMode) llclamp(mode, (S32) ALPHA_MODE_OPAQUE, (S32) ALPHA_MODE_MASK);
if (for_override)
{
// TODO: what do?
}
}
void LLGLTFMaterial::setDoubleSided(bool double_sided)
void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override)
{
// sure, no clamping will ever be needed for a bool, but include the
// setter for consistency with the clamping API
mDoubleSided = double_sided;
if (for_override)
{
// TODO: what do?
}
}
void LLGLTFMaterial::setTextureOffset(TextureInfo texture_info, const LLVector2& offset)
@ -373,101 +455,102 @@ void LLGLTFMaterial::setTextureRotation(TextureInfo texture_info, float rotation
mTextureTransform[texture_info].mRotation = rotation;
}
// Default value accessors
// Default value accessors (NOTE: these MUST match the GLTF specification)
// Make a static default material for accessors
const LLGLTFMaterial LLGLTFMaterial::sDefault;
LLUUID LLGLTFMaterial::getDefaultBaseColorId()
{
return LLUUID::null;
return sDefault.mBaseColorId;
}
LLUUID LLGLTFMaterial::getDefaultNormalId()
{
return LLUUID::null;
return sDefault.mNormalId;
}
LLUUID LLGLTFMaterial::getDefaultEmissiveId()
{
return LLUUID::null;
return sDefault.mEmissiveId;
}
LLUUID LLGLTFMaterial::getDefaultMetallicRoughnessId()
{
return LLUUID::null;
return sDefault.mMetallicRoughnessId;
}
F32 LLGLTFMaterial::getDefaultAlphaCutoff()
{
return 0.f;
return sDefault.mAlphaCutoff;
}
S32 LLGLTFMaterial::getDefaultAlphaMode()
{
return (S32) ALPHA_MODE_OPAQUE;
return (S32) sDefault.mAlphaMode;
}
F32 LLGLTFMaterial::getDefaultMetallicFactor()
{
return 0.f;
return sDefault.mMetallicFactor;
}
F32 LLGLTFMaterial::getDefaultRoughnessFactor()
{
return 0.f;
return sDefault.mRoughnessFactor;
}
LLColor4 LLGLTFMaterial::getDefaultBaseColor()
{
return LLColor4::white;
return sDefault.mBaseColor;
}
LLColor3 LLGLTFMaterial::getDefaultEmissiveColor()
{
return LLColor3::black;
return sDefault.mEmissiveColor;
}
bool LLGLTFMaterial::getDefaultDoubleSided()
{
return false;
return sDefault.mDoubleSided;
}
LLVector2 LLGLTFMaterial::getDefaultTextureOffset()
{
return LLVector2(0.f, 0.f);
return sDefault.mTextureTransform[0].mOffset;
}
LLVector2 LLGLTFMaterial::getDefaultTextureScale()
{
return LLVector2(1.f, 1.f);
return sDefault.mTextureTransform[0].mScale;
}
F32 LLGLTFMaterial::getDefaultTextureRotation()
{
return 0.f;
return sDefault.mTextureTransform[0].mRotation;
}
// static
void LLGLTFMaterial::applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id)
{
if (override_id != GLTF_OVERRIDE_NULL_UUID)
{
dst_id = override_id;
}
else
{
dst_id = LLUUID::null;
}
}
void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
{
// TODO: potentially reimplement this with a more general purpose JSON merge
LL_PROFILE_ZONE_SCOPED;
if (override_mat.mBaseColorId != getDefaultBaseColorId())
{
mBaseColorId = override_mat.mBaseColorId;
}
if (override_mat.mNormalId != getDefaultNormalId())
{
mNormalId = override_mat.mNormalId;
}
if (override_mat.mMetallicRoughnessId != getDefaultMetallicRoughnessId())
{
mMetallicRoughnessId = override_mat.mMetallicRoughnessId;
}
if (override_mat.mEmissiveId != getDefaultEmissiveId())
{
mEmissiveId = override_mat.mEmissiveId;
}
applyOverrideUUID(mBaseColorId, override_mat.mBaseColorId);
applyOverrideUUID(mNormalId, override_mat.mNormalId);
applyOverrideUUID(mMetallicRoughnessId, override_mat.mMetallicRoughnessId);
applyOverrideUUID(mEmissiveId, override_mat.mEmissiveId);
if (override_mat.mBaseColor != getDefaultBaseColor())
{

View File

@ -45,6 +45,9 @@ class LLGLTFMaterial : public LLRefCount
{
public:
// default material for reference
static const LLGLTFMaterial sDefault;
struct TextureTransform
{
LLVector2 mOffset = { 0.f, 0.f };
@ -69,12 +72,13 @@ public:
LLUUID mMetallicRoughnessId;
LLUUID mEmissiveId;
// NOTE : initialize values to defaults according to the GLTF spec
LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
F32 mMetallicFactor = 0.f;
F32 mRoughnessFactor = 0.f;
F32 mAlphaCutoff = 0.f;
F32 mMetallicFactor = 1.f;
F32 mRoughnessFactor = 1.f;
F32 mAlphaCutoff = 0.5f;
bool mDoubleSided = false;
AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
@ -105,19 +109,22 @@ public:
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
//setters for various members (will clamp to acceptable ranges)
// for_override - set to true if this value is being set as part of an override (important for handling override to default value)
void setBaseColorId(const LLUUID& id);
void setNormalId(const LLUUID& id);
void setMetallicRoughnessId(const LLUUID& id);
void setEmissiveId(const LLUUID& id);
void setBaseColorId(const LLUUID& id, bool for_override = false);
void setNormalId(const LLUUID& id, bool for_override = false);
void setMetallicRoughnessId(const LLUUID& id, bool for_override = false);
void setEmissiveId(const LLUUID& id, bool for_override = false);
void setBaseColorFactor(const LLColor3& baseColor, F32 transparency);
void setAlphaCutoff(F32 cutoff);
void setEmissiveColorFactor(const LLColor3& emissiveColor);
void setMetallicFactor(F32 metallic);
void setRoughnessFactor(F32 roughness);
void setAlphaMode(S32 mode);
void setDoubleSided(bool double_sided);
void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false);
void setAlphaCutoff(F32 cutoff, bool for_override = false);
void setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override = false);
void setMetallicFactor(F32 metallic, bool for_override = false);
void setRoughnessFactor(F32 roughness, bool for_override = false);
void setAlphaMode(S32 mode, bool for_override = false);
void setDoubleSided(bool double_sided, bool for_override = false);
//NOTE: texture offsets only exist in overrides, so "for_override" is not needed
void setTextureOffset(TextureInfo texture_info, const LLVector2& offset);
void setTextureScale(TextureInfo texture_info, const LLVector2& scale);
@ -139,34 +146,16 @@ public:
static LLVector2 getDefaultTextureScale();
static F32 getDefaultTextureRotation();
static void hackOverrideUUID(LLUUID& id);
static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id);
// set mAlphaMode from string.
// Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE
void setAlphaMode(const std::string& mode)
{
if (mode == "MASK")
{
mAlphaMode = ALPHA_MODE_MASK;
}
else if (mode == "BLEND")
{
mAlphaMode = ALPHA_MODE_BLEND;
}
else
{
mAlphaMode = ALPHA_MODE_OPAQUE;
}
}
const char* getAlphaMode() const
{
switch (mAlphaMode)
{
case ALPHA_MODE_MASK: return "MASK";
case ALPHA_MODE_BLEND: return "BLEND";
default: return "OPAQUE";
}
}
void setAlphaMode(const std::string& mode, bool for_override = false);
const char* getAlphaMode() const;
// set the contents of this LLGLTFMaterial from the given json
// returns true if successful
// json - the json text to load from

View File

@ -198,6 +198,7 @@ LLSD LLTextureEntry::asLLSD() const
void LLTextureEntry::asLLSD(LLSD& sd) const
{
LL_PROFILE_ZONE_SCOPED;
sd["imageid"] = mID;
sd["colors"] = ll_sd_from_color4(mColor);
sd["scales"] = mScaleS;
@ -225,6 +226,7 @@ void LLTextureEntry::asLLSD(LLSD& sd) const
bool LLTextureEntry::fromLLSD(const LLSD& sd)
{
LL_PROFILE_ZONE_SCOPED;
const char *w, *x;
w = "imageid";
if (sd.has(w))

View File

@ -235,6 +235,7 @@ public:
/*virtual*/ void setIsChrome(BOOL is_chrome);
/*virtual*/ void setRect(const LLRect &rect);
void setIsSingleInstance(BOOL is_single_instance);
BOOL getIsSingleInstance() { return mSingleInstance; }
void initFloater(const Params& p);

View File

@ -61,6 +61,7 @@ namespace
bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override
{
LL_PROFILE_ZONE_SCOPED;
// receive override data from simulator via LargeGenericMessage
// message should have:
// object_id - UUID of LLViewerObject
@ -196,6 +197,7 @@ void LLGLTFMaterialList::queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFM
void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj)
{
LL_PROFILE_ZONE_SCOPED;
const LLUUID& id = obj->getID();
auto iter = mQueuedOverrides.find(id);
@ -225,9 +227,11 @@ void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj)
LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)
{
LL_PROFILE_ZONE_SCOPED;
uuid_mat_map_t::iterator iter = mList.find(id);
if (iter == mList.end())
{
LL_PROFILE_ZONE_NAMED("gltf fetch")
LLFetchedGLTFMaterial* mat = new LLFetchedGLTFMaterial();
mList[id] = mat;
@ -242,55 +246,66 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)
gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL,
[=](const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status)
{
LL_PROFILE_ZONE_NAMED("gltf asset callback");
if (status)
{
LL_WARNS() << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL;
}
LLFileSystem file(id, asset_type, LLFileSystem::READ);
auto size = file.getSize();
if (!size)
std::vector<char> buffer;
{
LL_DEBUGS() << "Zero size material." << LL_ENDL;
mat->mFetching = false;
mat->unref();
return;
LL_PROFILE_ZONE_NAMED("gltf read asset");
LLFileSystem file(id, asset_type, LLFileSystem::READ);
auto size = file.getSize();
if (!size)
{
LL_DEBUGS() << "Zero size material." << LL_ENDL;
mat->mFetching = false;
mat->unref();
return;
}
buffer.resize(size);
file.read((U8*)&buffer[0], buffer.size());
}
std::vector<char> buffer;
buffer.resize(size);
file.read((U8*)&buffer[0], buffer.size());
LLSD asset;
// read file into buffer
std::istrstream str(&buffer[0], buffer.size());
if (LLSDSerialize::deserialize(asset, str, buffer.size()))
{
if (asset.has("version") && asset["version"] == "1.0")
LL_PROFILE_ZONE_NAMED("gltf deserialize asset");
LLSD asset;
// read file into buffer
std::istrstream str(&buffer[0], buffer.size());
if (LLSDSerialize::deserialize(asset, str, buffer.size()))
{
if (asset.has("type") && asset["type"].asString() == "GLTF 2.0")
if (asset.has("version") && asset["version"] == "1.0")
{
if (asset.has("data") && asset["data"].isString())
if (asset.has("type") && asset["type"].asString() == "GLTF 2.0")
{
std::string data = asset["data"];
std::string warn_msg, error_msg;
if (!mat->fromJSON(data, warn_msg, error_msg))
if (asset.has("data") && asset["data"].isString())
{
LL_WARNS() << "Failed to decode material asset: " << LL_ENDL;
LL_WARNS() << warn_msg << LL_ENDL;
LL_WARNS() << error_msg << LL_ENDL;
std::string data = asset["data"];
std::string warn_msg, error_msg;
if (!mat->fromJSON(data, warn_msg, error_msg))
{
LL_WARNS() << "Failed to decode material asset: " << LL_ENDL;
LL_WARNS() << warn_msg << LL_ENDL;
LL_WARNS() << error_msg << LL_ENDL;
}
}
}
}
}
}
else
{
LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL;
else
{
LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL;
}
}
mat->mFetching = false;

View File

@ -47,7 +47,6 @@
#include "llscrolllistctrl.h"
#include "lltinygltfhelper.h"
#include "llviewertexture.h"
#include "tinygltf/tiny_gltf.h"
/*=======================================*/
/* Formal declarations, constants, etc. */
@ -83,7 +82,7 @@ LLLocalGLTFMaterial::LLLocalGLTFMaterial(std::string filename, S32 index)
}
else
{
LL_WARNS() << "File of no valid extension given, local material creation aborted." << "\n"
LL_WARNS("GLTF") << "File of no valid extension given, local material creation aborted." << "\n"
<< "Filename: " << mFilename << LL_ENDL;
return; // no valid extension.
}
@ -180,7 +179,7 @@ bool LLLocalGLTFMaterial::updateSelf()
}
else
{
LL_WARNS() << "During the update process the following file was found" << "\n"
LL_WARNS("GLTF") << "During the update process the following file was found" << "\n"
<< "but could not be opened or decoded for " << LL_LOCAL_UPDATE_RETRIES << " attempts." << "\n"
<< "Filename: " << mFilename << "\n"
<< "Disabling further update attempts for this file." << LL_ENDL;
@ -199,7 +198,7 @@ bool LLLocalGLTFMaterial::updateSelf()
else
{
LL_WARNS() << "During the update process, the following file was not found." << "\n"
LL_WARNS("GLTF") << "During the update process, the following file was not found." << "\n"
<< "Filename: " << mFilename << "\n"
<< "Disabling further update attempts for this file." << LL_ENDL;
@ -234,120 +233,24 @@ bool LLLocalGLTFMaterial::loadMaterial()
case ET_MATERIAL_GLTF:
case ET_MATERIAL_GLB:
{
tinygltf::TinyGLTF loader;
std::string error_msg;
std::string warn_msg;
tinygltf::Model model_in;
std::string filename_lc = mFilename;
LLStringUtil::toLower(filename_lc);
std::string material_name;
// 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
decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
}
else
{ // file is ascii
decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
}
// Might be a good idea to make these textures into local textures
LLTinyGLTFHelper::getMaterialFromFile(
mFilename,
mMaterialIndex,
mGLTFMaterial,
material_name,
mBaseColorFetched,
mNormalFetched,
mMRFetched,
mEmissiveFetched);
if (!decode_successful)
if (!material_name.empty())
{
LL_WARNS() << "Cannot load Material, error: " << error_msg
<< ", warning:" << warn_msg
<< " file: " << mFilename
<< LL_ENDL;
break;
}
if (model_in.materials.size() <= mMaterialIndex)
{
// materials are missing
LL_WARNS() << "Cannot load Material, Material " << mMaterialIndex << " is missing, " << mFilename << LL_ENDL;
decode_successful = false;
break;
}
// sets everything, but textures will have inaccurate ids
mGLTFMaterial->setFromModel(model_in, mMaterialIndex);
std::string folder = gDirUtilp->getDirName(filename_lc);
tinygltf::Material material_in = model_in.materials[mMaterialIndex];
if (!material_in.name.empty())
{
mShortName = gDirUtilp->getBaseFileName(filename_lc, true) + " (" + material_in.name + ")";
}
// get base color texture
LLPointer<LLImageRaw> base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index);
// get normal map
LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index);
// get metallic-roughness texture
LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index);
// get emissive texture
LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(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 = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index);
}
// todo: pass it into local bitmaps?
LLTinyGLTFHelper::initFetchedTextures(material_in,
base_img, normal_img, mr_img, emissive_img, occlusion_img,
mBaseColorFetched, mNormalFetched, mMRFetched, mEmissiveFetched);
if (mBaseColorFetched)
{
mBaseColorFetched->addTextureStats(64.f * 64.f, TRUE);
mGLTFMaterial->mBaseColorId = mBaseColorFetched->getID();
mGLTFMaterial->mBaseColorTexture = mBaseColorFetched;
}
else
{
mGLTFMaterial->mBaseColorId = LLUUID::null;
mGLTFMaterial->mBaseColorTexture = nullptr;
}
if (mNormalFetched)
{
mNormalFetched->addTextureStats(64.f * 64.f, TRUE);
mGLTFMaterial->mNormalId = mNormalFetched->getID();
mGLTFMaterial->mNormalTexture = mBaseColorFetched;
}
else
{
mGLTFMaterial->mNormalId = LLUUID::null;
mGLTFMaterial->mNormalTexture = nullptr;
}
if (mMRFetched)
{
mMRFetched->addTextureStats(64.f * 64.f, TRUE);
mGLTFMaterial->mMetallicRoughnessId = mMRFetched->getID();
mGLTFMaterial->mMetallicRoughnessTexture = mBaseColorFetched;
}
else
{
mGLTFMaterial->mMetallicRoughnessId = LLUUID::null;
mGLTFMaterial->mMetallicRoughnessTexture = nullptr;
}
if (mEmissiveFetched)
{
mEmissiveFetched->addTextureStats(64.f * 64.f, TRUE);
mGLTFMaterial->mEmissiveId = mEmissiveFetched->getID();
mGLTFMaterial->mEmissiveTexture = mBaseColorFetched;
}
else
{
mGLTFMaterial->mEmissiveId = LLUUID::null;
mGLTFMaterial->mEmissiveTexture = nullptr;
mShortName = gDirUtilp->getBaseFileName(filename_lc, true) + " (" + material_name + ")";
}
break;
@ -359,9 +262,9 @@ bool LLLocalGLTFMaterial::loadMaterial()
// accessing mFilename and any other object properties might very well crash the viewer.
// getting here should be impossible, or there's been a pretty serious bug.
LL_WARNS() << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL;
LL_WARNS() << "Filename: " << mFilename << LL_ENDL;
LL_WARNS() << "Disabling further update attempts for this file." << LL_ENDL;
LL_WARNS("GLTF") << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL;
LL_WARNS("GLTF") << "Filename: " << mFilename << LL_ENDL;
LL_WARNS("GLTF") << "Disabling further update attempts for this file." << LL_ENDL;
mLinkStatus = LS_BROKEN;
}
}
@ -461,7 +364,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename)
if (!decode_successful)
{
LL_WARNS() << "Cannot load, error: Failed to decode" << error_msg
LL_WARNS("GLTF") << "Cannot load, error: Failed to decode" << error_msg
<< ", warning:" << warn_msg
<< " file: " << filename
<< LL_ENDL;
@ -471,7 +374,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename)
if (model_in.materials.empty())
{
// materials are missing
LL_WARNS() << "Cannot load. File has no materials " << filename << LL_ENDL;
LL_WARNS("GLTF") << "Cannot load. File has no materials " << filename << LL_ENDL;
return 0;
}
materials_in_file = model_in.materials.size();
@ -492,7 +395,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename)
}
else
{
LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n"
LL_WARNS("GLTF") << "Attempted to add invalid or unreadable image file, attempt cancelled.\n"
<< "Filename: " << filename << LL_ENDL;
LLSD notif_args;

View File

@ -65,26 +65,22 @@ 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";
// 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";
// Dirty flags
static const U32 MATERIAL_BASE_COLOR_DIRTY = 0x1 << 0;
static const U32 MATERIAL_BASE_TRANSPARENCY_DIRTY = 0x1 << 1;
static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 2;
static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 1;
static const U32 MATERIAL_NORMAL_TEX_DIRTY = 0x1 << 3;
static const U32 MATERIAL_NORMAL_TEX_DIRTY = 0x1 << 2;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY = 0x1 << 4;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY = 0x1 << 5;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY = 0x1 << 6;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY = 0x1 << 3;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY = 0x1 << 4;
static const U32 MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY = 0x1 << 5;
static const U32 MATERIAL_EMISIVE_COLOR_DIRTY = 0x1 << 7;
static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 8;
static const U32 MATERIAL_EMISIVE_COLOR_DIRTY = 0x1 << 6;
static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 7;
static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 9;
static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 10;
static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 11;
static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 8;
static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 9;
static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 10;
LLUUID LLMaterialEditor::mOverrideObjectId;
S32 LLMaterialEditor::mOverrideObjectTE = -1;
@ -327,8 +323,6 @@ 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)
@ -352,6 +346,10 @@ void LLMaterialEditor::setAuxItem(const LLInventoryItem* item)
BOOL LLMaterialEditor::postBuild()
{
// if this is a 'live editor' instance, it is also
// single instacne and uses live overrides
mIsOverride = getIsSingleInstance();
mBaseColorTextureCtrl = getChild<LLTextureCtrl>("base_color_texture");
mMetallicTextureCtrl = getChild<LLTextureCtrl>("metallic_roughness_texture");
mEmissiveTextureCtrl = getChild<LLTextureCtrl>("emissive_texture");
@ -362,15 +360,28 @@ BOOL LLMaterialEditor::postBuild()
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));
if (!mIsOverride)
{
childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this));
childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this));
childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this));
}
S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
if (mIsOverride)
{
childSetVisible("base_color_upload_fee", FALSE);
childSetVisible("metallic_upload_fee", FALSE);
childSetVisible("emissive_upload_fee", FALSE);
childSetVisible("normal_upload_fee", FALSE);
}
else
{
S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
}
boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void* userData)
{
@ -384,7 +395,7 @@ BOOL LLMaterialEditor::postBuild()
// BaseColor
childSetCommitCallback("base color", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_TRANSPARENCY_DIRTY);
childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY);
childSetCommitCallback("alpha cutoff", changes_callback, (void*)&MATERIAL_ALPHA_CUTOFF_DIRTY);
@ -395,9 +406,14 @@ BOOL LLMaterialEditor::postBuild()
// Emissive
childSetCommitCallback("emissive color", changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY);
childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
if (!mIsOverride)
{
// "unsaved_changes" doesn't exist in live editor
childSetVisible("unsaved_changes", mUnsavedChanges);
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
// Doesn't exist in live editor
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
}
// Todo:
// Disable/enable setCanApplyImmediately() based on
@ -408,7 +424,7 @@ BOOL LLMaterialEditor::postBuild()
void LLMaterialEditor::onClickCloseBtn(bool app_quitting)
{
if (app_quitting)
if (app_quitting || mIsOverride)
{
closeFloater(app_quitting);
}
@ -619,18 +635,27 @@ void LLMaterialEditor::setDoubleSided(bool double_sided)
void LLMaterialEditor::resetUnsavedChanges()
{
mUnsavedChanges = 0;
childSetVisible("unsaved_changes", false);
setCanSave(false);
if (!mIsOverride)
{
childSetVisible("unsaved_changes", false);
setCanSave(false);
mExpectedUploadCost = 0;
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
mExpectedUploadCost = 0;
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
}
}
void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
{
mUnsavedChanges |= dirty_flag;
// at the moment live editing (mIsOverride) applies everything 'live'
childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
if (!mIsOverride)
{
// at the moment live editing (mIsOverride) applies everything 'live'
// and "unsaved_changes", save/cancel buttons don't exist there
return;
}
childSetVisible("unsaved_changes", mUnsavedChanges);
if (mUnsavedChanges)
{
@ -674,12 +699,18 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
void LLMaterialEditor::setCanSaveAs(bool value)
{
childSetEnabled("save_as", value);
if (!mIsOverride)
{
childSetEnabled("save_as", value);
}
}
void LLMaterialEditor::setCanSave(bool value)
{
childSetEnabled("save", value);
if (!mIsOverride)
{
childSetEnabled("save", value);
}
}
void LLMaterialEditor::setEnableEditing(bool can_modify)
@ -711,21 +742,24 @@ void LLMaterialEditor::setEnableEditing(bool can_modify)
void LLMaterialEditor::onCommitBaseColorTexture(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 = mBaseColorTextureCtrl->getValue().asUUID();
if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull())
if (!mIsOverride)
{
childSetValue("base_color_upload_fee", getString("upload_fee_string"));
}
else
{
// Texture picker has 'apply now' with 'cancel' support.
// Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in
// case user decides to cancel changes.
// Without mBaseColorFetched, viewer will eventually cleanup
// the texture that is not in use
childSetValue("base_color_upload_fee", getString("no_upload_fee_string"));
// 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 = mBaseColorTextureCtrl->getValue().asUUID();
if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull())
{
childSetValue("base_color_upload_fee", getString("upload_fee_string"));
}
else
{
// Texture picker has 'apply now' with 'cancel' support.
// Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in
// case user decides to cancel changes.
// Without mBaseColorFetched, viewer will eventually cleanup
// the texture that is not in use
childSetValue("base_color_upload_fee", getString("no_upload_fee_string"));
}
}
markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY);
applyToSelection();
@ -733,14 +767,17 @@ void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & da
void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data)
{
LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID();
if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull())
if (!mIsOverride)
{
childSetValue("metallic_upload_fee", getString("upload_fee_string"));
}
else
{
childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
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"));
}
}
markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY);
applyToSelection();
@ -748,14 +785,17 @@ void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & dat
void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data)
{
LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID();
if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull())
if (!mIsOverride)
{
childSetValue("emissive_upload_fee", getString("upload_fee_string"));
}
else
{
childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
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"));
}
}
markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY);
applyToSelection();
@ -763,14 +803,17 @@ void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & dat
void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data)
{
LLUUID new_val = mNormalTextureCtrl->getValue().asUUID();
if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull())
if (!mIsOverride)
{
childSetValue("normal_upload_fee", getString("upload_fee_string"));
}
else
{
childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
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"));
}
}
markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY);
applyToSelection();
@ -1415,73 +1458,6 @@ void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD&
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
if (mIsOverride && !mObjectOverridesSavedValues.empty())
{
// Reapply ids back onto selection.
// TODO: monitor selection changes and resave on selection changes
struct g : public LLSelectedObjectFunctor
{
g(LLMaterialEditor* me) : mEditor(me) {}
virtual bool apply(LLViewerObject* objectp)
{
if (!objectp || !objectp->permModify())
{
return false;
}
U32 local_id = objectp->getLocalID();
if (mEditor->mObjectOverridesSavedValues.find(local_id) == mEditor->mObjectOverridesSavedValues.end())
{
return false;
}
S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
for (U8 te = 0; te < num_tes; te++)
{
if (mEditor->mObjectOverridesSavedValues[local_id].size() > te
&& objectp->getTE(te)->isSelected())
{
objectp->setRenderMaterialID(
te,
mEditor->mObjectOverridesSavedValues[local_id][te],
false /*wait for bulk update*/);
}
}
return true;
}
LLMaterialEditor* mEditor;
} restorefunc(this);
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&restorefunc);
struct f : public LLSelectedObjectFunctor
{
virtual bool apply(LLViewerObject* object)
{
if (object && !object->permModify())
{
return false;
}
LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
if (param_block)
{
if (param_block->isEmpty())
{
object->setHasRenderMaterialParams(false);
}
else
{
object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
}
}
object->sendTEUpdate();
return true;
}
} sendfunc;
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
}
closeFloater();
}
}
@ -1631,46 +1607,11 @@ void LLMaterialEditor::onSelectionChanged()
clearTextures();
setFromSelection();
}
// At the moment all cahges are 'live' so don't reset dirty flags
// saveLiveValues(); todo
}
void LLMaterialEditor::saveLiveValues()
{
// Collect ids to be able to revert overrides.
// TODO: monitor selection changes and resave on selection changes
mObjectOverridesSavedValues.clear();
struct g : public LLSelectedObjectFunctor
{
g(LLMaterialEditor* me) : mEditor(me) {}
virtual bool apply(LLViewerObject* objectp)
{
if (!objectp)
{
return false;
}
U32 local_id = objectp->getLocalID();
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);
}
return true;
}
LLMaterialEditor* mEditor;
} savefunc(this);
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&savefunc);
}
void LLMaterialEditor::updateLive()
{
const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key);
LLFloater* instance = LLFloaterReg::findInstance("live_material_editor");
if (instance && LLFloater::isVisible(instance))
{
LLMaterialEditor* me = (LLMaterialEditor*)instance;
@ -1691,8 +1632,7 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
// Not an update we are waiting for
return;
}
const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key);
LLFloater* instance = LLFloaterReg::findInstance("live_material_editor");
if (instance && LLFloater::isVisible(instance))
{
LLMaterialEditor* me = (LLMaterialEditor*)instance;
@ -1707,26 +1647,19 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
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);
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("live_material_editor");
if (me)
{
me->mOverrideInProgress = false;
me->setFromSelection();
me->setTitle(me->getString("material_override_title"));
me->childSetVisible("save", false);
me->childSetVisible("save_as", false);
// Set up for selection changes updates
if (!me->mSelectionUpdateSlot.connected())
{
me->mSelectionUpdateSlot = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLMaterialEditor::onSelectionChanged, me));
}
// Collect ids to be able to revert overrides on cancel.
me->saveLiveValues();
me->openFloater(floater_key);
me->openFloater();
me->setFocus(TRUE);
}
}
@ -2227,10 +2160,17 @@ private:
class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor
{
public:
LLRenderMaterialOverrideFunctor(LLMaterialEditor * me, std::string const & url)
: mEditor(me), mCapUrl(url)
LLRenderMaterialOverrideFunctor(
LLMaterialEditor * me,
std::string const & url,
const LLUUID &report_on_object_id,
S32 report_on_te)
: mEditor(me)
, mCapUrl(url)
, mSuccess(false)
, mObjectId(report_on_object_id)
, mObjectTE(report_on_te)
{
}
bool apply(LLViewerObject* objectp, S32 te) override
@ -2263,66 +2203,71 @@ public:
// Override object's values with values from editor where appropriate
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_DIRTY)
{
material->mBaseColor = mEditor->getBaseColor();
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_TRANSPARENCY_DIRTY)
{
material->mBaseColor.mV[3] = mEditor->getTransparency();
material->setBaseColorFactor(mEditor->getBaseColor(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_TEX_DIRTY)
{
material->mBaseColorId = mEditor->getBaseColorId();
material->setBaseColorId(mEditor->getBaseColorId(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_NORMAL_TEX_DIRTY)
{
material->mNormalId = mEditor->getNormalId();
material->setNormalId(mEditor->getNormalId(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY)
{
material->mMetallicRoughnessId = mEditor->getMetallicRoughnessId();
material->setMetallicRoughnessId(mEditor->getMetallicRoughnessId(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY)
{
material->mMetallicFactor = mEditor->getMetalnessFactor();
material->setMetallicFactor(mEditor->getMetalnessFactor(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY)
{
material->mRoughnessFactor = mEditor->getRoughnessFactor();
material->setRoughnessFactor(mEditor->getRoughnessFactor(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_COLOR_DIRTY)
{
material->mEmissiveColor = mEditor->getEmissiveColor();
material->setEmissiveColorFactor(LLColor3(mEditor->getEmissiveColor()), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_TEX_DIRTY)
{
material->mEmissiveId = mEditor->getEmissiveId();
material->setEmissiveId(mEditor->getEmissiveId(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_DOUBLE_SIDED_DIRTY)
{
material->mDoubleSided = mEditor->getDoubleSided();
material->setDoubleSided(mEditor->getDoubleSided(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_MODE_DIRTY)
{
material->setAlphaMode(mEditor->getAlphaMode());
material->setAlphaMode(mEditor->getAlphaMode(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_CUTOFF_DIRTY)
{
material->mAlphaCutoff = mEditor->getAlphaCutoff();
material->setAlphaCutoff(mEditor->getAlphaCutoff(), true);
}
std::string overrides_json = material->asJSON();
LLSD overrides = llsd::map(
"object_id", objectp->getID(),
"side", te,
"gltf_json", overrides_json
);
LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, modifyCallback));
void(*done_callback)(bool) = nullptr;
if (mObjectTE == te
&& mObjectId == objectp->getID())
{
mSuccess = true;
// We only want callback for face we are displayig material from
// even if we are setting all of them
done_callback = modifyCallback;
}
LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, done_callback));
}
return true;
}
@ -2334,12 +2279,17 @@ public:
// something went wrong update selection
LLMaterialEditor::updateLive();
}
// else we will get updateLive(obj, id) from aplied overrides
// else we will get updateLive(obj, id) from applied overrides
}
bool getResult() { return mSuccess; }
private:
LLMaterialEditor * mEditor;
std::string mCapUrl;
LLUUID mObjectId;
S32 mObjectTE;
bool mSuccess;
};
void LLMaterialEditor::applyToSelection()
@ -2363,9 +2313,11 @@ void LLMaterialEditor::applyToSelection()
{
mOverrideInProgress = true;
LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
LLRenderMaterialOverrideFunctor override_func(this, url);
if (!selected_objects->applyToTEs(&override_func))
LLRenderMaterialOverrideFunctor override_func(this, url, mOverrideObjectId, mOverrideObjectTE);
selected_objects->applyToTEs(&override_func);
if (!override_func.getResult())
{
// OverrideFunctor didn't find expected object or face
mOverrideInProgress = false;
}

View File

@ -104,7 +104,6 @@ public:
static void loadMaterialFromFile(const std::string& filename, S32 index = -1);
void onSelectionChanged(); // live overrides selection changes
void saveLiveValues(); // for restoration on cancel
static void updateLive();
static void updateLive(const LLUUID &object_id, S32 te);
@ -293,7 +292,6 @@ private:
// for "cancel" support
static LLUUID mOverrideObjectId; // static to avoid searching for the floater
static S32 mOverrideObjectTE;
std::map<U32, uuid_vec_t> mObjectOverridesSavedValues;
boost::signals2::connection mSelectionUpdateSlot;
};

View File

@ -2816,11 +2816,11 @@ void LLPanelFace::updateVisibility()
{
updateShinyControls();
}
getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_normal);
getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_normal);
getChildView("shinyRot")->setVisible(show_shininess || show_pbr_normal);
getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_normal);
getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_normal);
getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_metallic);
getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_metallic);
getChildView("shinyRot")->setVisible(show_shininess || show_pbr_metallic);
getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_metallic);
getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_metallic);
// Normal map controls
if (show_bumpiness)
@ -2830,11 +2830,11 @@ void LLPanelFace::updateVisibility()
getChildView("bumpytexture control")->setVisible(show_bumpiness);
getChildView("combobox bumpiness")->setVisible(show_bumpiness);
getChildView("label bumpiness")->setVisible(show_bumpiness);
getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_metallic);
getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_metallic);
getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_metallic);
getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_metallic);
getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_metallic);
getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_normal);
getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_normal);
getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_normal);
getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_normal);
getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_normal);
// PBR controls
getChildView("pbr_control")->setVisible(show_pbr);

View File

@ -181,3 +181,127 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny
return rawImage;
}
bool LLTinyGLTFHelper::getMaterialFromFile(
const std::string& filename,
S32 mat_index,
LLPointer < LLFetchedGLTFMaterial> material,
std::string& material_name,
LLPointer<LLViewerFetchedTexture>& base_color_tex,
LLPointer<LLViewerFetchedTexture>& normal_tex,
LLPointer<LLViewerFetchedTexture>& mr_tex,
LLPointer<LLViewerFetchedTexture>& emissive_tex)
{
tinygltf::TinyGLTF loader;
std::string error_msg;
std::string warn_msg;
tinygltf::Model model_in;
std::string filename_lc = filename;
bool decode_successful = true;
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
decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
}
else
{ // file is ascii
decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
}
if (!decode_successful)
{
LL_WARNS("GLTF") << "Cannot load Material, error: " << error_msg
<< ", warning:" << warn_msg
<< " file: " << filename
<< LL_ENDL;
return false;
}
else if (model_in.materials.size() <= mat_index)
{
// materials are missing
LL_WARNS("GLTF") << "Cannot load Material, Material " << mat_index << " is missing, " << filename << LL_ENDL;
return false;
}
material->setFromModel(model_in, mat_index);
std::string folder = gDirUtilp->getDirName(filename_lc);
tinygltf::Material material_in = model_in.materials[mat_index];
material_name = material_in.name;
// get base color texture
LLPointer<LLImageRaw> base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index);
// get normal map
LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index);
// get metallic-roughness texture
LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index);
// get emissive texture
LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(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 = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index);
}
// todo: pass it into local bitmaps?
LLTinyGLTFHelper::initFetchedTextures(material_in,
base_img, normal_img, mr_img, emissive_img, occlusion_img,
base_color_tex, normal_tex, mr_tex, emissive_tex);
if (base_color_tex)
{
base_color_tex->addTextureStats(64.f * 64.f, TRUE);
material->mBaseColorId = base_color_tex->getID();
material->mBaseColorTexture = base_color_tex;
}
else
{
material->mBaseColorId = LLUUID::null;
material->mBaseColorTexture = nullptr;
}
if (normal_tex)
{
normal_tex->addTextureStats(64.f * 64.f, TRUE);
material->mNormalId = normal_tex->getID();
material->mNormalTexture = normal_tex;
}
else
{
material->mNormalId = LLUUID::null;
material->mNormalTexture = nullptr;
}
if (mr_tex)
{
mr_tex->addTextureStats(64.f * 64.f, TRUE);
material->mMetallicRoughnessId = mr_tex->getID();
material->mMetallicRoughnessTexture = mr_tex;
}
else
{
material->mMetallicRoughnessId = LLUUID::null;
material->mMetallicRoughnessTexture = nullptr;
}
if (emissive_tex)
{
emissive_tex->addTextureStats(64.f * 64.f, TRUE);
material->mEmissiveId = emissive_tex->getID();
material->mEmissiveTexture = emissive_tex;
}
else
{
material->mEmissiveId = LLUUID::null;
material->mEmissiveTexture = nullptr;
}
return true;
}

View File

@ -27,6 +27,7 @@
#pragma once
#include "llgltfmaterial.h"
#include "llgltfmateriallist.h"
#include "llpointer.h"
#include "tinygltf/tiny_gltf.h"
@ -40,6 +41,18 @@ namespace LLTinyGLTFHelper
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name);
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
bool getMaterialFromFile(
const std::string& filename,
S32 mat_index,
LLPointer < LLFetchedGLTFMaterial> material,
std::string& material_name,
LLPointer<LLViewerFetchedTexture>& base_color_tex,
LLPointer<LLViewerFetchedTexture>& normal_tex,
LLPointer<LLViewerFetchedTexture>& mr_tex,
LLPointer<LLViewerFetchedTexture>& emissive_tex);
void initFetchedTextures(tinygltf::Material& material,
LLPointer<LLImageRaw>& base_color_img,
LLPointer<LLImageRaw>& normal_img,

View File

@ -418,6 +418,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
LLFloaterReg::add("live_material_editor", "floater_live_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);

View File

@ -5523,6 +5523,7 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_mat)
{
LL_PROFILE_ZONE_SCOPED;
S32 retval = TEM_CHANGE_NONE;
LLTextureEntry* tep = getTE(te);

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
can_resize="true"
default_tab_group="1"
height="786"
width="256"
min_height="500"
min_width="256"
layout="topleft"
name="material editor"
help_topic="material_editor"
single_instance="true"
title="Editing Material">
<scroll_container
name="materials_scroll"
top="14"
left="4"
height="768"
width="247"
follows="all"
layout="topleft"
color="DkGray2"
opaque="true"
reserve_scroll_corner="false">
<panel
name="panel_material"
filename="panel_gltf_material.xml"
border="false"
visible="true"
layout="topleft"
top="0"
left="0"
height="768"
width="247" />
</scroll_container>
</floater>

View File

@ -27,430 +27,17 @@
layout="topleft"
color="DkGray2"
opaque="true"
reserve_scroll_corner="false"
>
reserve_scroll_corner="false">
<panel
border="false"
name="scroll_panel"
top="0"
left="0"
height="768"
width="247"
>
<check_box
follows="left|top"
label="Double Sided"
left="10"
top="0"
name="double sided"
height="25"
width="120" />
<panel
border="true"
follows="left|top"
width="246"
height="196"
layout="topleft"
left="1"
mouse_opaque="false"
name="base_color_texture_pnl"
top_pad="5"
>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="128">
Base Color:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="base_color_texture"
tool_tip="Base Color map. Alpha channel is optional and used for transparency."
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="base_color_upload_fee"
>
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8"
>
Tint
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
left_delta="0"
top_pad="5"
name="base color"
width="40" />
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96"
>
Transparency
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="1"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="transparency"
width="64"
/>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
name="label alphamode"
text_readonly_color="LabelDisabledColor"
top_pad="5"
width="90">
Alpha mode
</text>
<combo_box
height="23"
layout="topleft"
left_delta="0"
name="alpha mode"
top_pad="4"
width="96">
<combo_box.item
label="None"
name="None"
value="OPAQUE" />
<combo_box.item
label="Alpha blending"
name="Alpha blending"
value="BLEND" />
<combo_box.item
label="Alpha masking"
name="Alpha masking"
value="MASK" />
</combo_box>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96"
>
Alpha Cutoff
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="1"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="alpha cutoff"
width="64"
/>
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
name="metallic_texture_pnl"
top_pad="5"
>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
>
Metallic-Roughness:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
width="128"
height="151"
layout="topleft"
left="10"
name="metallic_roughness_texture"
tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
top_pad="8"
/>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="metallic_upload_fee"
>
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8"
>
Metallic Factor
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="metalness factor"
width="64"
/>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96"
>
Roughness Factor
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="roughness factor"
width="64"
/>
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
name="emissive_texture_pnl"
top_pad="5"
>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="64">
Emissive:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="emissive_texture"
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="emissive_upload_fee"
>
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8"
>
Tint
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
left_delta="0"
top_pad="5"
name="emissive color"
width="40" />
<!--<text
type="string"
length="1"
follows="left|top"
height="10"
width="64"
layout="topleft"
left_delta="0"
top_pad="5"
>
Intensity
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
max_val="100"
width="64"
/>-->
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
top_pad="5"
name="normal_texture_pnl"
>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="64">
Normal:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="normal_texture"
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="normal_upload_fee"
>
No upload fee
</text>
</panel>
</panel>
name="panel_material"
filename="panel_gltf_material.xml"
border="false"
visible="true"
layout="topleft"
top="0"
left="0"
height="768"
width="247" />
</scroll_container>
<panel

View File

@ -0,0 +1,382 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
layout="topleft"
follows="all"
border="false"
name="panel_gltf_material"
top="0"
left="0"
height="768"
width="247">
<check_box
follows="left|top"
layout="topleft"
label="Double Sided"
left="10"
top="0"
name="double sided"
height="25"
width="120" />
<panel
border="true"
follows="left|top"
width="246"
height="196"
layout="topleft"
left="1"
mouse_opaque="false"
name="base_color_texture_pnl"
top_pad="5"
>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="128">
Base Color:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="base_color_texture"
tool_tip="Base Color map. Alpha channel is optional and used for transparency."
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="base_color_upload_fee">
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8">
Tint
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
left_delta="0"
top_pad="5"
name="base color"
width="40" />
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96">
Transparency
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="1"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="transparency"
width="64"/>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
name="label alphamode"
text_readonly_color="LabelDisabledColor"
top_pad="5"
width="90">
Alpha mode
</text>
<combo_box
height="23"
layout="topleft"
left_delta="0"
name="alpha mode"
top_pad="4"
width="96">
<combo_box.item
label="Opaque"
name="None"
value="OPAQUE" />
<combo_box.item
label="Blend"
name="Alpha blending"
value="BLEND" />
<combo_box.item
label="Mask"
name="Alpha masking"
value="MASK" />
</combo_box>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96">
Alpha Cutoff
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="1"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="alpha cutoff"
width="64"/>
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
name="metallic_texture_pnl"
top_pad="5">
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5">
Metallic-Roughness:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
width="128"
height="151"
layout="topleft"
left="10"
name="metallic_roughness_texture"
tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
top_pad="8"/>
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="metallic_upload_fee">
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8">
Metallic Factor
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="metalness factor"
width="64"/>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96">
Roughness Factor
</text>
<spinner
decimal_digits="3"
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="1"
name="roughness factor"
width="64"/>
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
name="emissive_texture_pnl"
top_pad="5">
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="64">
Emissive:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="emissive_texture"
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="emissive_upload_fee">
No upload fee
</text>
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_pad="5"
top="8">
Tint
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
left_delta="0"
top_pad="5"
name="emissive color"
width="40" />
</panel>
<panel
border="true"
follows="left|top"
width="246"
height="175"
layout="topleft"
left="1"
mouse_opaque="false"
top_pad="5"
name="normal_texture_pnl">
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
layout="topleft"
left="10"
top="5"
width="64">
Normal:
</text>
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
allow_no_texture="true"
follows="left|top"
top_pad="8"
height="151"
layout="topleft"
left="10"
name="normal_texture"
width="128" />
<text
type="string"
font.style="BOLD"
length="1"
follows="left|top"
height="10"
width="128"
layout="topleft"
left="10"
top_pad="-17"
name="normal_upload_fee">
No upload fee
</text>
</panel>
</panel>