diff options
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/gltf/animation.h | 2 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.cpp | 332 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.h | 66 | ||||
| -rw-r--r-- | indra/newview/gltfscenemanager.cpp | 43 | ||||
| -rw-r--r-- | indra/newview/gltfscenemanager.h | 3 | ||||
| -rw-r--r-- | indra/newview/llfilepicker.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/lltinygltfhelper.cpp | 37 | ||||
| -rw-r--r-- | indra/newview/lltinygltfhelper.h | 1 | ||||
| -rw-r--r-- | indra/newview/llviewermenu.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 24 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 13 | 
12 files changed, 525 insertions, 17 deletions
diff --git a/indra/newview/gltf/animation.h b/indra/newview/gltf/animation.h index 869eae963a..cc2045ebb2 100644 --- a/indra/newview/gltf/animation.h +++ b/indra/newview/gltf/animation.h @@ -81,8 +81,6 @@ namespace LL                  S32 mSampler = INVALID_INDEX;                  Target mTarget; -                std::string mTargetPath; -                std::string mName;                  const Channel& operator=(const tinygltf::AnimationChannel& src)                  { diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 313e82bf01..233faac545 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -33,6 +33,267 @@  using namespace LL::GLTF; + +namespace LL +{ +    namespace GLTF +    { +        template <typename T, typename U> +        void copy(const std::vector<T>& src, std::vector<U>& dst) +        { +            dst.resize(src.size()); +            for (U32 i = 0; i < src.size(); ++i) +            { +                copy(src[i], dst[i]); +            } +        } + +        void copy(const Node& src, tinygltf::Node& dst) +        { +            if (src.mMatrixValid) +            { +                if (!src.mMatrix.asMatrix4().isIdentity()) +                { +                    dst.matrix.resize(16); +                    for (U32 i = 0; i < 16; ++i) +                    { +                        dst.matrix[i] = src.mMatrix.getF32ptr()[i]; +                    } +                } +            } +            else if (src.mTRSValid) +            { +                if (!src.mRotation.equals(glh::quaternionf::identity(), FLT_EPSILON)) +                { +                    dst.rotation.resize(4); +                    for (U32 i = 0; i < 4; ++i) +                    { +                        dst.rotation[i] = src.mRotation.get_value()[i]; +                    } +                }    +                 +                if (src.mTranslation != glh::vec3f(0.f, 0.f, 0.f)) +                { +                    dst.translation.resize(3); +                    for (U32 i = 0; i < 3; ++i) +                    { +                        dst.translation[i] = src.mTranslation.v[i]; +                    } +                } +                 +                if (src.mScale != glh::vec3f(1.f, 1.f, 1.f)) +                { +                    dst.scale.resize(3); +                    for (U32 i = 0; i < 3; ++i) +                    { +                        dst.scale[i] = src.mScale.v[i]; +                    } +                } +            } + +            dst.children = src.mChildren; +            dst.mesh = src.mMesh; +            dst.skin = src.mSkin; +            dst.name = src.mName; +        } + +        void copy(const Scene& src, tinygltf::Scene& dst) +        { +            dst.nodes = src.mNodes; +            dst.name = src.mName; +        } + +        void copy(const Primitive& src, tinygltf::Primitive& dst) +        { +            for (auto& attrib : src.mAttributes) +            { +                dst.attributes[attrib.first] = attrib.second; +            } +            dst.indices = src.mIndices; +            dst.material = src.mMaterial; +            dst.mode = src.mMode; +        } + +        void copy(const Mesh& src, tinygltf::Mesh& mesh) +        { +            copy(src.mPrimitives, mesh.primitives); +            mesh.weights = src.mWeights; +            mesh.name = src.mName; +        } + +        void copy(const Material::TextureInfo& src, tinygltf::TextureInfo& dst) +        { +            dst.index = src.mIndex; +            dst.texCoord = src.mTexCoord; +        } + +        void copy(const Material::OcclusionTextureInfo& src, tinygltf::OcclusionTextureInfo& dst) +        { +            dst.index = src.mIndex; +            dst.texCoord = src.mTexCoord; +            dst.strength = src.mStrength; +        } + +        void copy(const Material::NormalTextureInfo& src, tinygltf::NormalTextureInfo& dst) +        { +            dst.index = src.mIndex; +            dst.texCoord = src.mTexCoord; +            dst.scale = src.mScale; +        } + +        void copy(const Material::PbrMetallicRoughness& src, tinygltf::PbrMetallicRoughness& dst) +        { +            dst.baseColorFactor = { src.mBaseColorFactor.v[0], src.mBaseColorFactor.v[1], src.mBaseColorFactor.v[2], src.mBaseColorFactor.v[3] }; +            copy(src.mBaseColorTexture, dst.baseColorTexture); +            dst.metallicFactor = src.mMetallicFactor; +            dst.roughnessFactor = src.mRoughnessFactor; +            copy(src.mMetallicRoughnessTexture, dst.metallicRoughnessTexture); +        } + +        void copy(const Material& src, tinygltf::Material& material) +        { +            material.name = src.mName; + +            material.emissiveFactor = { src.mEmissiveFactor.v[0], src.mEmissiveFactor.v[1], src.mEmissiveFactor.v[2] }; +            copy(src.mPbrMetallicRoughness, material.pbrMetallicRoughness); +            copy(src.mNormalTexture, material.normalTexture); +            copy(src.mEmissiveTexture, material.emissiveTexture); +        } + +        void copy(const Texture& src, tinygltf::Texture& texture) +        { +            texture.sampler = src.mSampler; +            texture.source = src.mSource; +            texture.name = src.mName; +        } + +        void copy(const Sampler& src, tinygltf::Sampler& sampler) +        { +            sampler.magFilter = src.mMagFilter; +            sampler.minFilter = src.mMinFilter; +            sampler.wrapS = src.mWrapS; +            sampler.wrapT = src.mWrapT; +            sampler.name = src.mName; +        } + +        void copy(const Skin& src, tinygltf::Skin& skin) +        { +            skin.joints = src.mJoints; +            skin.inverseBindMatrices = src.mInverseBindMatrices; +            skin.skeleton = src.mSkeleton; +            skin.name = src.mName; +        } + +        void copy(const Accessor& src, tinygltf::Accessor& accessor) +        { +            accessor.bufferView = src.mBufferView; +            accessor.byteOffset = src.mByteOffset; +            accessor.componentType = src.mComponentType; +            accessor.minValues = src.mMin; +            accessor.maxValues = src.mMax; +             +            accessor.count = src.mCount; +            accessor.type = src.mType; +            accessor.normalized = src.mNormalized; +            accessor.name = src.mName; +        } + +        void copy(const Animation::Sampler& src, tinygltf::AnimationSampler& sampler) +        { +            sampler.input = src.mInput; +            sampler.output = src.mOutput; +            sampler.interpolation = src.mInterpolation; +        } + +        void copy(const Animation::Channel& src, tinygltf::AnimationChannel& channel) +        { +            channel.sampler = src.mSampler; +            channel.target_node = src.mTarget.mNode; +            channel.target_path = src.mTarget.mPath; +        } + +        void copy(const Animation& src, tinygltf::Animation& animation) +        { +            animation.name = src.mName; + +            copy(src.mSamplers, animation.samplers); + +            U32 channel_count = src.mRotationChannels.size() + src.mTranslationChannels.size() + src.mScaleChannels.size(); + +            animation.channels.resize(channel_count); + +            U32 idx = 0; +            for (U32 i = 0; i < src.mTranslationChannels.size(); ++i) +            { +                copy(src.mTranslationChannels[i], animation.channels[idx++]); +            } + +            for (U32 i = 0; i < src.mRotationChannels.size(); ++i) +            { +                copy(src.mRotationChannels[i], animation.channels[idx++]); +            } + +            for (U32 i = 0; i < src.mScaleChannels.size(); ++i) +            { +                copy(src.mScaleChannels[i], animation.channels[idx++]); +            } +        } + +        void copy(const Buffer& src, tinygltf::Buffer& buffer) +        { +            buffer.uri = src.mUri; +            buffer.data = src.mData; +            buffer.name = src.mName; +        } + +        void copy(const BufferView& src, tinygltf::BufferView& bufferView) +        { +            bufferView.buffer = src.mBuffer; +            bufferView.byteOffset = src.mByteOffset; +            bufferView.byteLength = src.mByteLength; +            bufferView.byteStride = src.mByteStride; +            bufferView.target = src.mTarget; +            bufferView.name = src.mName; +        } + +        void copy(const Image& src, tinygltf::Image& image) +        { +            image.name = src.mName; +            image.width = src.mWidth; +            image.height = src.mHeight; +            image.component = src.mComponent; +            image.bits = src.mBits; +            image.pixel_type = src.mPixelType; + +            image.image = src.mData; +            image.bufferView = src.mBufferView; +            image.mimeType = src.mMimeType; +            image.uri = src.mUri; +        } + +        void copy(const Asset & src, tinygltf::Model& dst) +        { +            dst.defaultScene = src.mDefaultScene; +            dst.asset.copyright = src.mCopyright; +            dst.asset.version = src.mVersion; +            dst.asset.minVersion = src.mMinVersion; +            dst.asset.generator = "Linden Lab Experimental GLTF Export"; + +            copy(src.mScenes, dst.scenes); +            copy(src.mNodes, dst.nodes); +            copy(src.mMeshes, dst.meshes); +            copy(src.mMaterials, dst.materials); +            copy(src.mBuffers, dst.buffers); +            copy(src.mBufferViews, dst.bufferViews); +            copy(src.mTextures, dst.textures); +            copy(src.mSamplers, dst.samplers); +            copy(src.mImages, dst.images); +            copy(src.mAccessors, dst.accessors); +            copy(src.mAnimations, dst.animations); +            copy(src.mSkins, dst.skins); +        } +    } +}  void Scene::updateTransforms(Asset& asset)  {      LLMatrix4a identity; @@ -237,6 +498,8 @@ void Node::makeMatrixValid()          mMatrix.loadu(t.m);          mMatrixValid = true;      } + +    llassert(mMatrixValid);  }  void Node::makeTRSValid() @@ -252,6 +515,8 @@ void Node::makeTRSValid()          mRotation.set_value(t);          mTRSValid = true;      } + +    llassert(mTRSValid);  }  void Node::setRotation(const glh::quaternionf& q) @@ -318,6 +583,7 @@ const Node& Node::operator=(const tinygltf::Node& src)      {          // node specifies no transformation, set to identity          mMatrix.setIdentity(); +        mMatrixValid = true;      }      mChildren = src.children; @@ -467,6 +733,14 @@ void Asset::allocateGLResources(const std::string& filename, const tinygltf::Mod  const Asset& Asset::operator=(const tinygltf::Model& src)  { +    mVersion = src.asset.version; +    mMinVersion = src.asset.minVersion; +    mGenerator = src.asset.generator; +    mCopyright = src.asset.copyright; + +    mDefaultScene = src.defaultScene; + +      mScenes.resize(src.scenes.size());      for (U32 i = 0; i < src.scenes.size(); ++i)      { @@ -542,9 +816,67 @@ const Asset& Asset::operator=(const tinygltf::Model& src)      return *this;  } +void Asset::save(tinygltf::Model& dst) +{ +    LL::GLTF::copy(*this, dst); +} + + +const Material::TextureInfo& Material::TextureInfo::operator=(const tinygltf::TextureInfo& src) +{ +    mIndex = src.index; +    mTexCoord = src.texCoord; +    return *this; +} + +const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const tinygltf::OcclusionTextureInfo& src) +{ +    mIndex = src.index; +    mTexCoord = src.texCoord; +    mStrength = src.strength; +    return *this; +} + +const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const tinygltf::NormalTextureInfo& src) +{ +    mIndex = src.index; +    mTexCoord = src.texCoord; +    mScale = src.scale; +    return *this; +} + +const Material::PbrMetallicRoughness& Material::PbrMetallicRoughness::operator=(const tinygltf::PbrMetallicRoughness& src) +{ +    if (src.baseColorFactor.size() == 4) +    { +        mBaseColorFactor.set_value(src.baseColorFactor[0], src.baseColorFactor[1], src.baseColorFactor[2], src.baseColorFactor[3]); +    } +     +    mBaseColorTexture = src.baseColorTexture; +    mMetallicFactor = src.metallicFactor; +    mRoughnessFactor = src.roughnessFactor; +    mMetallicRoughnessTexture = src.metallicRoughnessTexture; + +    return *this; +}  const Material& Material::operator=(const tinygltf::Material& src)  {      mName = src.name; +     +    if (src.emissiveFactor.size() == 3) +    { +        mEmissiveFactor.set_value(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]); +    } + +    mPbrMetallicRoughness = src.pbrMetallicRoughness; +    mNormalTexture = src.normalTexture; +    mOcclusionTexture = src.occlusionTexture; +    mEmissiveTexture = src.emissiveTexture; + +    mAlphaMode = src.alphaMode; +    mAlphaCutoff = src.alphaCutoff; +    mDoubleSided = src.doubleSided; +      return *this;  } diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 6e576a1ffe..b8300c2d8a 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -45,11 +45,59 @@ namespace LL          class Material          {          public: +            class TextureInfo +            { +            public: +                S32 mIndex = INVALID_INDEX; +                S32 mTexCoord = 0; + +                const TextureInfo& operator=(const tinygltf::TextureInfo& src); +            }; + +            class NormalTextureInfo : public TextureInfo +            { +            public: +                F32 mScale = 1.0f; + +                const NormalTextureInfo& operator=(const tinygltf::NormalTextureInfo& src); +            }; + +            class OcclusionTextureInfo : public TextureInfo +            { +            public: +                F32 mStrength = 1.0f; + +                const OcclusionTextureInfo& operator=(const tinygltf::OcclusionTextureInfo& src); +            }; + +            class PbrMetallicRoughness +            { +            public: +                glh::vec4f mBaseColorFactor = glh::vec4f(1.f,1.f,1.f,1.f); +                TextureInfo mBaseColorTexture; +                F32 mMetallicFactor = 1.0f; +                F32 mRoughnessFactor = 1.0f; +                TextureInfo mMetallicRoughnessTexture; +                const PbrMetallicRoughness& operator=(const tinygltf::PbrMetallicRoughness& src); +            }; + +              // use LLFetchedGLTFMaterial for now, but eventually we'll want to use              // a more flexible GLTF material implementation instead of the fixed packing              // version we use for sharable GLTF material assets              LLPointer<LLFetchedGLTFMaterial> mMaterial; +            PbrMetallicRoughness mPbrMetallicRoughness; +            NormalTextureInfo mNormalTexture; +            OcclusionTextureInfo mOcclusionTexture; +            TextureInfo mEmissiveTexture; + +              std::string mName; +            glh::vec3f mEmissiveFactor = glh::vec3f(0.f, 0.f, 0.f); +            std::string mAlphaMode = "OPAQUE"; +            F32 mAlphaCutoff = 0.5f; +            bool mDoubleSided = false; +              const Material& operator=(const tinygltf::Material& src); @@ -179,11 +227,16 @@ namespace LL              std::string mName;              std::string mUri;              std::string mMimeType; + +            S32 mBufferView = INVALID_INDEX; +              std::vector<U8> mData;              S32 mWidth;              S32 mHeight;              S32 mComponent;              S32 mBits; +            S32 mPixelType; +              LLPointer<LLViewerFetchedTexture> mTexture;              const Image& operator=(const tinygltf::Image& src) @@ -196,7 +249,8 @@ namespace LL                  mHeight = src.height;                  mComponent = src.component;                  mBits = src.bits; - +                mBufferView = src.bufferView; +                mPixelType = src.pixel_type;                  return *this;              } @@ -224,6 +278,13 @@ namespace LL              std::vector<Animation> mAnimations;              std::vector<Skin> mSkins; +            std::string mVersion; +            std::string mGenerator; +            std::string mMinVersion; +            std::string mCopyright; + +            S32 mDefaultScene = INVALID_INDEX; +              // the last time update() was called according to gFrameTimeSeconds              F32 mLastUpdateTime = gFrameTimeSeconds; @@ -258,6 +319,9 @@ namespace LL              );              const Asset& operator=(const tinygltf::Model& src); + +            // save the asset to a tinygltf model +            void save(tinygltf::Model& dst);          };      } diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 4e3439ea5c..f9f1240469 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -66,11 +66,50 @@ void GLTFSceneManager::load()                  }              },              LLFilePicker::FFLOAD_GLTF, -            true); +            false);      }      else      { -        LLNotificationsUtil::add("GLTFPreviewSelection"); +        LLNotificationsUtil::add("GLTFOpenSelection"); +    } +} + +void GLTFSceneManager::saveAs() +{ +    LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject(); +    if (obj && obj->mGLTFAsset.notNull()) +    { +        LLFilePickerReplyThread::startPicker( +            [](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter) +            { +                if (LLAppViewer::instance()->quitRequested()) +                { +                    return; +                } +                if (filenames.size() > 0) +                { +                    GLTFSceneManager::instance().save(filenames[0]); +                } +            }, +            LLFilePicker::FFSAVE_GLTF, +            "scene.gltf"); +    } +    else +    { +        LLNotificationsUtil::add("GLTFSaveSelection"); +    } +} + +void GLTFSceneManager::save(const std::string& filename) +{ +    LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject(); +    if (obj && obj->mGLTFAsset.notNull()) +    { +        Asset* asset = obj->mGLTFAsset; +        tinygltf::Model model; +        asset->save(model); + +        LLTinyGLTFHelper::saveModel(filename, model);      }  } diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index d286f335e4..ec50a0952f 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -40,6 +40,9 @@ namespace LL          void load(); // open filepicker to choose asset          void load(const std::string& filename); // load asset from filename +        void saveAs(); // open filepicker and choose file to save selected asset to +        void save(const std::string& filename); // save selected asset to filename +          void update();          void render(bool opaque, bool rigged = false);          void renderOpaque(); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index b82172c506..23d9b25344 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -790,7 +790,7 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,          case LLFilePicker::FFSAVE_GLTF:              type = "\?\?\?\?";              creator = "\?\?\?\?"; -            extension = "glb"; +            extension = "glb,gltf";              break;          case LLFilePicker::FFSAVE_XML: diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 49c35165e6..c8a9a36ad1 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -248,6 +248,43 @@ bool LLTinyGLTFHelper::loadModel(const std::string& filename, tinygltf::Model& m      return false;  } +bool LLTinyGLTFHelper::saveModel(const std::string& filename, tinygltf::Model& model_in) +{ +    std::string exten = gDirUtilp->getExtension(filename); + +    bool success = false; + +    if (exten == "gltf" || exten == "glb") +    { +        tinygltf::TinyGLTF writer; + +        std::string filename_lc = filename; +        LLStringUtil::toLower(filename_lc); + +         +        bool embed_images = false; +        bool embed_buffers = false; +        bool pretty_print = true; +        bool write_binary = false; +         + +        if (std::string::npos == filename_lc.rfind(".gltf")) +        {  // file is binary +            embed_images = embed_buffers = write_binary = true; +        } + +        success = writer.WriteGltfSceneToFile(&model_in, filename, embed_images, embed_buffers, pretty_print, write_binary); + +        if (!success) +        { +            LL_WARNS("GLTF") << "Failed to save" << LL_ENDL; +            return false; +        } +    } + +    return success; +} +  bool LLTinyGLTFHelper::getMaterialFromModel(      const std::string& filename,      const tinygltf::Model& model_in, diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h index da505b41e9..a259609404 100644 --- a/indra/newview/lltinygltfhelper.h +++ b/indra/newview/lltinygltfhelper.h @@ -42,6 +42,7 @@ namespace LLTinyGLTFHelper      LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, bool flip = true);      bool loadModel(const std::string& filename, tinygltf::Model& model_out); +    bool saveModel(const std::string& filename, tinygltf::Model& model_in);      bool getMaterialFromModel(          const std::string& filename, diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c1a8c5df9e..fcda8fa767 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7980,7 +7980,7 @@ class LLAdvancedClickHDRIPreview: public view_listener_t  }; -class LLAdvancedClickGLTFScenePreview : public view_listener_t +class LLAdvancedClickGLTFOpen: public view_listener_t  {      bool handleEvent(const LLSD& userdata)      { @@ -7990,6 +7990,16 @@ class LLAdvancedClickGLTFScenePreview : public view_listener_t      }  }; +class LLAdvancedClickGLTFSaveAs : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        // open personal lighting floater when previewing an HDRI (keeps HDRI from implicitly unloading when opening build tools) +        LL::GLTFSceneManager::instance().saveAs(); +        return true; +    } +}; +  // these are used in the gl menus to set control values that require shader recompilation  class LLToggleShaderControl : public view_listener_t  { @@ -9637,7 +9647,8 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile");  	view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark");      view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview"); -    view_listener_t::addMenu(new LLAdvancedClickGLTFScenePreview(), "Advanced.ClickGLTFScenePreview"); +    view_listener_t::addMenu(new LLAdvancedClickGLTFOpen(), "Advanced.ClickGLTFOpen"); +    view_listener_t::addMenu(new LLAdvancedClickGLTFSaveAs(), "Advanced.ClickGLTFSaveAs");  	view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");      view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b66d4b1dab..5b21040a04 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4379,7 +4379,7 @@ LLMatrix4a LLViewerObject::getGLTFAssetToAgentTransform() const      LLMatrix4 root;      root.initScale(getScale());      root.rotate(getRenderRotation()); -    root.translate(getPositionAgent()); +    root.translate(getRenderPosition());      LLMatrix4a mat;      mat.loadu((F32*)root.mMatrix); @@ -4403,7 +4403,7 @@ LLMatrix4a LLViewerObject::getAgentToGLTFAssetTransform() const      scale.mV[1] = 1.f / scale.mV[1];      scale.mV[2] = 1.f / scale.mV[2]; -    root.translate(-getPositionAgent()); +    root.translate(-getRenderPosition());      root.rotate(~getRenderRotation());      LLMatrix4 scale_mat; diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 644553e64c..9544a926f3 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2844,6 +2844,24 @@ function="World.EnvPreset"                  parameter="mem_leaking" />                 </menu_item_call>          </menu> +      <menu +         create_jump_keys="true" +         label="GLTF" +         name="GLTF" +         tear_off="true"> +        <menu_item_call +         label="Open..." +         name="Open..."> +          <menu_item_call.on_click +           function="Advanced.ClickGLTFOpen" /> +        </menu_item_call> +        <menu_item_call +         label="Save As..." +         name="Save As..."> +          <menu_item_call.on_click +           function="Advanced.ClickGLTFSaveAs" /> +        </menu_item_call> +      </menu>          <menu           create_jump_keys="true"           label="Render Tests" @@ -2896,12 +2914,6 @@ function="World.EnvPreset"              <menu_item_call.on_click               function="Advanced.ClickHDRIPreview" />            </menu_item_call> -          <menu_item_call -           label="GLTF Scene Preview" -           name="GLTF Scene Preview"> -            <menu_item_call.on_click -             function="Advanced.ClickGLTFScenePreview" /> -          </menu_item_call>          </menu>        <menu          create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index ad1f12002e..7d7ea986dd 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -12408,7 +12408,7 @@ are wearing now.    <notification     icon="alertmodal.tga" -   name="GLTFPreviewSelection" +   name="GLTFOpenSelection"     type="alert">      You must select an object to act as a handle to the GLTF asset you are previewing.      <tag>fail</tag> @@ -12417,4 +12417,15 @@ are wearing now.        yestext="OK"/>    </notification> +  <notification +   icon="alertmodal.tga" +   name="GLTFSaveSelection" +   type="alert"> +    You must select an object that has a GLTF asset associated with it. +    <tag>fail</tag> +    <usetemplate +      name="okbutton" +      yestext="OK"/> +  </notification> +  </notifications>  | 
