This commit is contained in:
Lirusaito
2013-07-16 09:50:58 -04:00
50 changed files with 2413 additions and 314 deletions

View File

@@ -33,6 +33,7 @@
#include "llvisualparam.h"
#include "llavatarappearancedefines.h"
#include "llwearable.h"
#include "lldate.h"
using namespace LLAvatarAppearanceDefines;
@@ -68,47 +69,42 @@ LLAssetType::EType LLWearable::getAssetType() const
return LLWearableType::getAssetType(mType);
}
// reX: new function
BOOL LLWearable::FileExportParams( FILE* file ) const
extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
// Replace '--' with '- -', see http://en.wikipedia.org/wiki/XML#Comments
std::string XMLCommentEscape(std::string const& comment)
{
// wearable type
S32 type = (S32)mType;
fprintf( file, "type %d\n", type );
// parameters
S32 num_parameters = mVisualParamIndexMap.size();
fprintf( file, "parameters %d\n", num_parameters );
for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin();
iter != mVisualParamIndexMap.end(); ++iter)
{
S32 param_id = iter->first;
F32 param_weight = iter->second->getWeight();
fprintf( file, "%d %s\n", param_id, terse_F32_to_string(param_weight).c_str() );
}
return TRUE;
std::string result = comment;
std::string::size_type off = std::string::npos;
while ((off = result.rfind("--", off)) != std::string::npos)
{
result.replace(off, 2, "- -");
}
return result;
}
// reX: new function
BOOL LLWearable::FileExportTextures( FILE* file ) const
void LLWearable::archetypeExport(LLAPRFile& file) const
{
// wearable type
S32 type = (S32)mType;
fprintf( file, "type %d\n", type );
apr_file_t* fp = file.getFileHandle();
// texture entries
S32 num_textures = mTEMap.size();
fprintf( file, "textures %d\n", num_textures );
for (te_map_t::const_iterator iter = mTEMap.begin();
iter != mTEMap.end(); ++iter)
apr_file_printf(fp, "\n\t\t<!-- wearable: %s -->\n", getTypeName().c_str());
apr_file_printf(fp, "\t\t<!-- Name : %s -->\n", XMLCommentEscape(mName).c_str());
apr_file_printf(fp, "\t\t<!-- Description: %s -->\n", XMLCommentEscape(mDescription).c_str());
apr_file_printf(fp, "\t\t<!-- date: %s -->\n", LLDate::now().asString().c_str());
for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
{
LLVisualParam const* param = iter->second;
dump_visual_param(file, param, param->getWeight());
}
for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
{
S32 te = iter->first;
fprintf( file, "%d %s\n", te, iter->second->getID().asString().c_str() );
}
LLUUID const& image_id = iter->second->getID();
apr_file_printf(fp, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, image_id.asString().c_str());
}
return TRUE;
apr_file_printf(fp, "\n");
}
BOOL LLWearable::exportFile(LLFILE* fp) const

View File

@@ -35,6 +35,7 @@
#include "llwearabletype.h"
#include "lllocaltextureobject.h"
class LLAPRFile;
class LLMD5;
class LLVisualParam;
class LLTexGlobalColorInfo;
@@ -77,9 +78,8 @@ public:
virtual void writeToAvatar(LLAvatarAppearance* avatarp);
BOOL FileExportParams(FILE* file) const;
BOOL FileExportTextures(FILE* file) const;
void archetypeExport(LLAPRFile& file) const;
enum EImportResult
{
FAILURE = 0,

View File

@@ -940,6 +940,7 @@ P(lcl_responder);
P(MPImportGetResponder);
P(MPImportPostResponder);
P(mapLayerResponder);
P(materialsResponder);
P2(maturityPreferences, transfer_30s_connect_10s);
P(mediaDataClientResponder);
P(mediaTypeResponder);

View File

@@ -20,6 +20,8 @@ include_directories(
)
set(llprimitive_SOURCE_FILES
llmaterialid.cpp
llmaterial.cpp
llmaterialtable.cpp
llmediaentry.cpp
llmodel.cpp
@@ -37,6 +39,8 @@ set(llprimitive_HEADER_FILES
CMakeLists.txt
legacy_object_types.h
llmaterial.h
llmaterialid.h
llmaterialtable.h
llmediaentry.h
llmodel.h

View File

@@ -0,0 +1,227 @@
/**
* @file llmaterial.cpp
* @brief Material definition
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmaterial.h"
/**
* Materials cap parameters
*/
#define MATERIALS_CAP_NORMAL_MAP_FIELD "NormMap"
#define MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD "NormOffsetX"
#define MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD "NormOffsetY"
#define MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD "NormRepeatX"
#define MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD "NormRepeatY"
#define MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD "NormRotation"
#define MATERIALS_CAP_SPECULAR_MAP_FIELD "SpecMap"
#define MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD "SpecOffsetX"
#define MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD "SpecOffsetY"
#define MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD "SpecRepeatX"
#define MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD "SpecRepeatY"
#define MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD "SpecRotation"
#define MATERIALS_CAP_SPECULAR_COLOR_FIELD "SpecColor"
#define MATERIALS_CAP_SPECULAR_EXP_FIELD "SpecExp"
#define MATERIALS_CAP_ENV_INTENSITY_FIELD "EnvIntensity"
#define MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD "AlphaMaskCutoff"
#define MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD "DiffuseAlphaMode"
const LLColor4U LLMaterial::DEFAULT_SPECULAR_LIGHT_COLOR(255,255,255,255);
/**
* Materials constants
*/
const F32 MATERIALS_MULTIPLIER = 10000.f;
/**
* Helper functions
*/
template<typename T> T getMaterialField(const LLSD& data, const std::string& field, const LLSD::Type field_type)
{
if ( (data.has(field)) && (field_type == data[field].type()) )
{
return (T)data[field];
}
llerrs << "Missing or mistyped field '" << field << "' in material definition" << llendl;
return (T)LLSD();
}
// GCC didn't like the generic form above for some reason
template<> LLUUID getMaterialField(const LLSD& data, const std::string& field, const LLSD::Type field_type)
{
if ( (data.has(field)) && (field_type == data[field].type()) )
{
return data[field].asUUID();
}
llerrs << "Missing or mistyped field '" << field << "' in material definition" << llendl;
return LLUUID::null;
}
/**
* LLMaterial class
*/
const LLMaterial LLMaterial::null;
LLMaterial::LLMaterial()
: mNormalOffsetX(0.0f)
, mNormalOffsetY(0.0f)
, mNormalRepeatX(1.0f)
, mNormalRepeatY(1.0f)
, mNormalRotation(0.0f)
, mSpecularOffsetX(0.0f)
, mSpecularOffsetY(0.0f)
, mSpecularRepeatX(1.0f)
, mSpecularRepeatY(1.0f)
, mSpecularRotation(0.0f)
, mSpecularLightColor(LLMaterial::DEFAULT_SPECULAR_LIGHT_COLOR)
, mSpecularLightExponent(LLMaterial::DEFAULT_SPECULAR_LIGHT_EXPONENT)
, mEnvironmentIntensity(LLMaterial::DEFAULT_ENV_INTENSITY)
, mDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
, mAlphaMaskCutoff(0)
{
}
LLMaterial::LLMaterial(const LLSD& material_data)
{
fromLLSD(material_data);
}
LLSD LLMaterial::asLLSD() const
{
LLSD material_data;
material_data[MATERIALS_CAP_NORMAL_MAP_FIELD] = mNormalID;
material_data[MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD] = llround(mNormalOffsetX * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD] = llround(mNormalOffsetY * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD] = llround(mNormalRepeatX * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD] = llround(mNormalRepeatY * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD] = llround(mNormalRotation * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_MAP_FIELD] = mSpecularID;
material_data[MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD] = llround(mSpecularOffsetX * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD] = llround(mSpecularOffsetY * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD] = llround(mSpecularRepeatX * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD] = llround(mSpecularRepeatY * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD] = llround(mSpecularRotation * MATERIALS_MULTIPLIER);
material_data[MATERIALS_CAP_SPECULAR_COLOR_FIELD] = mSpecularLightColor.getValue();
material_data[MATERIALS_CAP_SPECULAR_EXP_FIELD] = mSpecularLightExponent;
material_data[MATERIALS_CAP_ENV_INTENSITY_FIELD] = mEnvironmentIntensity;
material_data[MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD] = mDiffuseAlphaMode;
material_data[MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD] = mAlphaMaskCutoff;
return material_data;
}
void LLMaterial::fromLLSD(const LLSD& material_data)
{
mNormalID = getMaterialField<LLSD::UUID>(material_data, MATERIALS_CAP_NORMAL_MAP_FIELD, LLSD::TypeUUID);
mNormalOffsetX = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mNormalOffsetY = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mNormalRepeatX = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mNormalRepeatY = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mNormalRotation = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularID = getMaterialField<LLSD::UUID>(material_data, MATERIALS_CAP_SPECULAR_MAP_FIELD, LLSD::TypeUUID);
mSpecularOffsetX = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularOffsetY = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularRepeatX = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularRepeatY = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularRotation = (F32)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD, LLSD::TypeInteger) / MATERIALS_MULTIPLIER;
mSpecularLightColor.setValue(getMaterialField<LLSD>(material_data, MATERIALS_CAP_SPECULAR_COLOR_FIELD, LLSD::TypeArray));
mSpecularLightExponent = (U8)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_SPECULAR_EXP_FIELD, LLSD::TypeInteger);
mEnvironmentIntensity = (U8)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_ENV_INTENSITY_FIELD, LLSD::TypeInteger);
mDiffuseAlphaMode = (U8)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD, LLSD::TypeInteger);
mAlphaMaskCutoff = (U8)getMaterialField<LLSD::Integer>(material_data, MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD, LLSD::TypeInteger);
}
bool LLMaterial::isNull() const
{
return (*this == null);
}
bool LLMaterial::operator == (const LLMaterial& rhs) const
{
return
(mNormalID == rhs.mNormalID) && (mNormalOffsetX == rhs.mNormalOffsetX) && (mNormalOffsetY == rhs.mNormalOffsetY) &&
(mNormalRepeatX == rhs.mNormalRepeatX) && (mNormalRepeatY == rhs.mNormalRepeatY) && (mNormalRotation == rhs.mNormalRotation) &&
(mSpecularID == rhs.mSpecularID) && (mSpecularOffsetX == rhs.mSpecularOffsetX) && (mSpecularOffsetY == rhs.mSpecularOffsetY) &&
(mSpecularRepeatX == rhs.mSpecularRepeatX) && (mSpecularRepeatY == rhs.mSpecularRepeatY) && (mSpecularRotation == rhs.mSpecularRotation) &&
(mSpecularLightColor == rhs.mSpecularLightColor) && (mSpecularLightExponent == rhs.mSpecularLightExponent) &&
(mEnvironmentIntensity == rhs.mEnvironmentIntensity) && (mDiffuseAlphaMode == rhs.mDiffuseAlphaMode) && (mAlphaMaskCutoff == rhs.mAlphaMaskCutoff);
}
bool LLMaterial::operator != (const LLMaterial& rhs) const
{
return !(*this == rhs);
}
U32 LLMaterial::getShaderMask(U32 alpha_mode)
{ //NEVER incorporate this value into the message system -- this function will vary depending on viewer implementation
U32 ret = 0;
//two least significant bits are "diffuse alpha mode"
if (alpha_mode != DIFFUSE_ALPHA_MODE_DEFAULT)
{
ret = alpha_mode;
}
else
{
ret = getDiffuseAlphaMode();
}
llassert(ret < SHADER_COUNT);
//next bit is whether or not specular map is present
const U32 SPEC_BIT = 0x4;
if (getSpecularID().notNull())
{
ret |= SPEC_BIT;
}
llassert(ret < SHADER_COUNT);
//next bit is whether or not normal map is present
const U32 NORM_BIT = 0x8;
if (getNormalID().notNull())
{
ret |= NORM_BIT;
}
llassert(ret < SHADER_COUNT);
return ret;
}

View File

@@ -0,0 +1,155 @@
/**
* @file llmaterial.h
* @brief Material definition
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLMATERIAL_H
#define LL_LLMATERIAL_H
#include <boost/shared_ptr.hpp>
#include "llmaterialid.h"
#include "llsd.h"
#include "v4coloru.h"
#include "llpointer.h"
#include "llrefcount.h"
class LLMaterial : public LLRefCount
{
public:
typedef enum
{
DIFFUSE_ALPHA_MODE_NONE = 0,
DIFFUSE_ALPHA_MODE_BLEND = 1,
DIFFUSE_ALPHA_MODE_MASK = 2,
DIFFUSE_ALPHA_MODE_EMISSIVE = 3,
DIFFUSE_ALPHA_MODE_DEFAULT = 4,
} eDiffuseAlphaMode;
typedef enum
{
SHADER_COUNT = 16,
ALPHA_SHADER_COUNT = 4
} eShaderCount;
static const U8 DEFAULT_SPECULAR_LIGHT_EXPONENT = ((U8)(0.2f * 255));
static const LLColor4U DEFAULT_SPECULAR_LIGHT_COLOR;
static const U8 DEFAULT_ENV_INTENSITY = 0;
LLMaterial();
LLMaterial(const LLSD& material_data);
LLSD asLLSD() const;
void fromLLSD(const LLSD& material_data);
const LLUUID& getNormalID() const { return mNormalID; }
void setNormalID(const LLUUID& normal_id) { mNormalID = normal_id; }
void getNormalOffset(F32& offset_x, F32& offset_y) const { offset_x = mNormalOffsetX; offset_y = mNormalOffsetY; }
F32 getNormalOffsetX() const { return mNormalOffsetX; }
F32 getNormalOffsetY() const { return mNormalOffsetY; }
void setNormalOffset(F32 offset_x, F32 offset_y) { mNormalOffsetX = offset_x; mNormalOffsetY = offset_y; }
void setNormalOffsetX(F32 offset_x) { mNormalOffsetX = offset_x; }
void setNormalOffsetY(F32 offset_y) { mNormalOffsetY = offset_y; }
void getNormalRepeat(F32& repeat_x, F32& repeat_y) const { repeat_x = mNormalRepeatX; repeat_y = mNormalRepeatY; }
F32 getNormalRepeatX() const { return mNormalRepeatX; }
F32 getNormalRepeatY() const { return mNormalRepeatY; }
void setNormalRepeat(F32 repeat_x, F32 repeat_y) { mNormalRepeatX = repeat_x; mNormalRepeatY = repeat_y; }
void setNormalRepeatX(F32 repeat_x) { mNormalRepeatX = repeat_x; }
void setNormalRepeatY(F32 repeat_y) { mNormalRepeatY = repeat_y; }
F32 getNormalRotation() const { return mNormalRotation; }
void setNormalRotation(F32 rot) { mNormalRotation = rot; }
const LLUUID& getSpecularID() const { return mSpecularID; }
void setSpecularID(const LLUUID& specular_id) { mSpecularID = specular_id; }
void getSpecularOffset(F32& offset_x, F32& offset_y) const { offset_x = mSpecularOffsetX; offset_y = mSpecularOffsetY; }
F32 getSpecularOffsetX() const { return mSpecularOffsetX; }
F32 getSpecularOffsetY() const { return mSpecularOffsetY; }
void setSpecularOffset(F32 offset_x, F32 offset_y) { mSpecularOffsetX = offset_x; mSpecularOffsetY = offset_y; }
void setSpecularOffsetX(F32 offset_x) { mSpecularOffsetX = offset_x; }
void setSpecularOffsetY(F32 offset_y) { mSpecularOffsetY = offset_y; }
void getSpecularRepeat(F32& repeat_x, F32& repeat_y) const { repeat_x = mSpecularRepeatX; repeat_y = mSpecularRepeatY; }
F32 getSpecularRepeatX() const { return mSpecularRepeatX; }
F32 getSpecularRepeatY() const { return mSpecularRepeatY; }
void setSpecularRepeat(F32 repeat_x, F32 repeat_y) { mSpecularRepeatX = repeat_x; mSpecularRepeatY = repeat_y; }
void setSpecularRepeatX(F32 repeat_x) { mSpecularRepeatX = repeat_x; }
void setSpecularRepeatY(F32 repeat_y) { mSpecularRepeatY = repeat_y; }
F32 getSpecularRotation() const { return mSpecularRotation; }
void setSpecularRotation(F32 rot) { mSpecularRotation = rot; }
const LLColor4U getSpecularLightColor() const { return mSpecularLightColor; }
void setSpecularLightColor(const LLColor4U& color) { mSpecularLightColor = color; }
U8 getSpecularLightExponent() const { return mSpecularLightExponent; }
void setSpecularLightExponent(U8 exponent) { mSpecularLightExponent = exponent; }
U8 getEnvironmentIntensity() const { return mEnvironmentIntensity; }
void setEnvironmentIntensity(U8 intensity) { mEnvironmentIntensity = intensity; }
U8 getDiffuseAlphaMode() const { return mDiffuseAlphaMode; }
void setDiffuseAlphaMode(U8 alpha_mode) { mDiffuseAlphaMode = alpha_mode; }
U8 getAlphaMaskCutoff() const { return mAlphaMaskCutoff; }
void setAlphaMaskCutoff(U8 cutoff) { mAlphaMaskCutoff = cutoff; }
bool isNull() const;
static const LLMaterial null;
bool operator == (const LLMaterial& rhs) const;
bool operator != (const LLMaterial& rhs) const;
U32 getShaderMask(U32 alpha_mode = DIFFUSE_ALPHA_MODE_DEFAULT);
protected:
LLUUID mNormalID;
F32 mNormalOffsetX;
F32 mNormalOffsetY;
F32 mNormalRepeatX;
F32 mNormalRepeatY;
F32 mNormalRotation;
LLUUID mSpecularID;
F32 mSpecularOffsetX;
F32 mSpecularOffsetY;
F32 mSpecularRepeatX;
F32 mSpecularRepeatY;
F32 mSpecularRotation;
LLColor4U mSpecularLightColor;
U8 mSpecularLightExponent;
U8 mEnvironmentIntensity;
U8 mDiffuseAlphaMode;
U8 mAlphaMaskCutoff;
};
typedef LLPointer<LLMaterial> LLMaterialPtr;
#endif // LL_LLMATERIAL_H

View File

@@ -0,0 +1,183 @@
/**
* @file llmaterialid.cpp
* @brief Implementation of llmaterialid
* @author Stinson@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmaterialid.h"
#include <string>
#include "llformat.h"
const LLMaterialID LLMaterialID::null;
LLMaterialID::LLMaterialID()
{
clear();
}
LLMaterialID::LLMaterialID(const LLSD& pMaterialID)
{
llassert(pMaterialID.isBinary());
parseFromBinary(pMaterialID.asBinary());
}
LLMaterialID::LLMaterialID(const LLSD::Binary& pMaterialID)
{
parseFromBinary(pMaterialID);
}
LLMaterialID::LLMaterialID(const void* pMemory)
{
set(pMemory);
}
LLMaterialID::LLMaterialID(const LLMaterialID& pOtherMaterialID)
{
copyFromOtherMaterialID(pOtherMaterialID);
}
LLMaterialID::~LLMaterialID()
{
}
bool LLMaterialID::operator == (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) == 0);
}
bool LLMaterialID::operator != (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) != 0);
}
bool LLMaterialID::operator < (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) < 0);
}
bool LLMaterialID::operator <= (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) <= 0);
}
bool LLMaterialID::operator > (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) > 0);
}
bool LLMaterialID::operator >= (const LLMaterialID& pOtherMaterialID) const
{
return (compareToOtherMaterialID(pOtherMaterialID) >= 0);
}
LLMaterialID& LLMaterialID::operator = (const LLMaterialID& pOtherMaterialID)
{
copyFromOtherMaterialID(pOtherMaterialID);
return (*this);
}
bool LLMaterialID::isNull() const
{
return (compareToOtherMaterialID(LLMaterialID::null) == 0);
}
const U8* LLMaterialID::get() const
{
return mID;
}
void LLMaterialID::set(const void* pMemory)
{
llassert(pMemory != NULL);
// assumes that the required size of memory is available
memcpy(mID, pMemory, MATERIAL_ID_SIZE * sizeof(U8));
}
void LLMaterialID::clear()
{
memset(mID, 0, MATERIAL_ID_SIZE * sizeof(U8));
}
LLSD LLMaterialID::asLLSD() const
{
LLSD::Binary materialIDBinary;
materialIDBinary.resize(MATERIAL_ID_SIZE * sizeof(U8));
memcpy(materialIDBinary.data(), mID, MATERIAL_ID_SIZE * sizeof(U8));
LLSD materialID = materialIDBinary;
return materialID;
}
std::string LLMaterialID::asString() const
{
std::string materialIDString;
for (unsigned int i = 0U; i < static_cast<unsigned int>(MATERIAL_ID_SIZE / sizeof(U32)); ++i)
{
if (i != 0U)
{
materialIDString += "-";
}
const U32 *value = reinterpret_cast<const U32*>(&get()[i * sizeof(U32)]);
materialIDString += llformat("%08x", *value);
}
return materialIDString;
}
std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id)
{
s << material_id.asString();
return s;
}
void LLMaterialID::parseFromBinary (const LLSD::Binary& pMaterialID)
{
llassert(pMaterialID.size() == (MATERIAL_ID_SIZE * sizeof(U8)));
memcpy(mID, &pMaterialID[0], MATERIAL_ID_SIZE * sizeof(U8));
}
void LLMaterialID::copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID)
{
memcpy(mID, pOtherMaterialID.get(), MATERIAL_ID_SIZE * sizeof(U8));
}
int LLMaterialID::compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const
{
int retVal = 0;
for (unsigned int i = 0U; (retVal == 0) && (i < static_cast<unsigned int>(MATERIAL_ID_SIZE / sizeof(U32))); ++i)
{
const U32 *thisValue = reinterpret_cast<const U32*>(&get()[i * sizeof(U32)]);
const U32 *otherValue = reinterpret_cast<const U32*>(&pOtherMaterialID.get()[i * sizeof(U32)]);
retVal = ((*thisValue < *otherValue) ? -1 : ((*thisValue > *otherValue) ? 1 : 0));
}
return retVal;
}

View File

@@ -0,0 +1,76 @@
/**
* @file llmaterialid.h
* @brief Header file for llmaterialid
* @author Stinson@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLMATERIALID_H
#define LL_LLMATERIALID_H
#define MATERIAL_ID_SIZE 16
#include <string>
class LLMaterialID
{
public:
LLMaterialID();
LLMaterialID(const LLSD& pMaterialID);
LLMaterialID(const LLSD::Binary& pMaterialID);
LLMaterialID(const void* pMemory);
LLMaterialID(const LLMaterialID& pOtherMaterialID);
~LLMaterialID();
bool operator == (const LLMaterialID& pOtherMaterialID) const;
bool operator != (const LLMaterialID& pOtherMaterialID) const;
bool operator < (const LLMaterialID& pOtherMaterialID) const;
bool operator <= (const LLMaterialID& pOtherMaterialID) const;
bool operator > (const LLMaterialID& pOtherMaterialID) const;
bool operator >= (const LLMaterialID& pOtherMaterialID) const;
LLMaterialID& operator = (const LLMaterialID& pOtherMaterialID);
bool isNull() const;
const U8* get() const;
void set(const void* pMemory);
void clear();
LLSD asLLSD() const;
std::string asString() const;
friend std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id);
static const LLMaterialID null;
private:
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const;
U8 mID[MATERIAL_ID_SIZE];
} ;
#endif // LL_LLMATERIALID_H

View File

@@ -309,6 +309,15 @@ S32 LLPrimitive::setTERotation(const U8 index, const F32 r)
return mTextureList.setRotation(index, r);
}
S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID)
{
return mTextureList.setMaterialID(index, pMaterialID);
}
S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
{
return mTextureList.setMaterialParams(index, pMaterialParams);
}
//===============================================================
S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump)
@@ -356,6 +365,23 @@ S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow)
return mTextureList.setGlow(index, glow);
}
void LLPrimitive::setAllTESelected(bool sel)
{
for (int i = 0, cnt = getNumTEs(); i < cnt; i++)
{
setTESelected(i, sel);
}
}
void LLPrimitive::setTESelected(const U8 te, bool sel)
{
LLTextureEntry* tep = getTE(te);
if ( (tep) && (tep->setSelected(sel)) && (!sel) && (tep->hasPendingMaterialUpdate()) )
{
LLMaterialID material_id = tep->getMaterialID();
setTEMaterialID(te, material_id);
}
}
LLPCode LLPrimitive::legacyToPCode(const U8 legacy)
{
@@ -1080,6 +1106,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1117,6 +1144,9 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
bump[face_index] = te->getBumpShinyFullbright();
media_flags[face_index] = te->getMediaTexGen();
glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
// Directly sending material_ids is not safe!
memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */
}
cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
@@ -1138,6 +1168,8 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID);
}
mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer));
@@ -1159,6 +1191,7 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1196,6 +1229,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
bump[face_index] = te->getBumpShinyFullbright();
media_flags[face_index] = te->getMediaTexGen();
glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
// Directly sending material_ids is not safe!
memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */
}
cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
@@ -1217,6 +1253,8 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID);
}
dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry");
@@ -1226,6 +1264,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec)
{
S32 retval = 0;
// temp buffer for material ID processing
// data will end up in tec.material_id[]
U8 material_data[LLTEContents::MAX_TES*16];
if (block_num < 0)
{
@@ -1251,7 +1292,7 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name
mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER);
}
tec.face_count = getNumTEs();
tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES);
U8 *cur_ptr = tec.packed_buffer;
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID);
@@ -1274,6 +1315,21 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8);
if (cur_ptr < tec.packed_buffer + tec.size)
{
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)material_data, 16, tec.face_count, MVT_LLUUID);
}
else
{
memset(material_data, 0, sizeof(material_data));
}
for (U32 i = 0; i < tec.face_count; i++)
{
tec.material_ids[i].set(&material_data[i * 16]);
}
retval = 1;
return retval;
}
@@ -1294,6 +1350,9 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
retval |= setTEBumpShinyFullbright(i, tec.bump[i]);
retval |= setTEMediaTexGen(i, tec.media_flags[i]);
retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF);
retval |= setTEMaterialID(i, tec.material_ids[i]);
coloru = LLColor4U(tec.colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
@@ -1328,6 +1387,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
// Avoid construction of 32 UUIDs per call
static LLUUID image_ids[MAX_TES];
static LLMaterialID material_ids[MAX_TES];
U8 image_data[MAX_TES*16];
U8 colors[MAX_TES*4];
@@ -1339,6 +1399,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1381,10 +1442,20 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
if (cur_ptr < packed_buffer + size)
{
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID);
}
else
{
memset(material_data, 0, sizeof(material_data));
}
for (i = 0; i < face_count; i++)
{
memcpy(image_ids[i].mData,&image_data[i*16],16); /* Flawfinder: ignore */
material_ids[i].set(&material_data[i * 16]);
}
LLColor4 color;
@@ -1398,6 +1469,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
retval |= setTEBumpShinyFullbright(i, bump[i]);
retval |= setTEMediaTexGen(i, media_flags[i]);
retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
retval |= setTEMaterialID(i, material_ids[i]);
coloru = LLColor4U(colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)

View File

@@ -42,6 +42,7 @@ class LLMessageSystem;
class LLVolumeParams;
class LLColor4;
class LLColor3;
class LLMaterialID;
class LLTextureEntry;
class LLDataPacker;
class LLVolumeMgr;
@@ -309,6 +310,7 @@ struct LLTEContents
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
LLMaterialID material_ids[MAX_TES];
static const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -359,6 +361,7 @@ public:
LLTextureEntry* getTE(const U8 te_num) const;
virtual void setNumTEs(const U8 num_tes);
virtual void setAllTESelected(bool sel);
virtual void setAllTETextures(const LLUUID &tex_id);
virtual void setTE(const U8 index, const LLTextureEntry& te);
virtual S32 setTEColor(const U8 te, const LLColor4 &color);
@@ -381,7 +384,10 @@ public:
virtual S32 setTEFullbright(const U8 te, const U8 fullbright);
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
virtual void setTESelected(const U8 te, bool sel);
void copyTEs(const LLPrimitive *primitive);
S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;

View File

@@ -27,6 +27,7 @@
#include "linden_common.h"
#include "llprimtexturelist.h"
#include "llmaterialid.h"
#include "lltextureentry.h"
// static
@@ -358,6 +359,24 @@ S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow)
return TEM_CHANGE_NONE;
}
S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMaterialID)
{
if (index < mEntryList.size())
{
return mEntryList[index]->setMaterialID(pMaterialID);
}
return TEM_CHANGE_NONE;
}
S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
{
if (index < mEntryList.size())
{
return mEntryList[index]->setMaterialParams(pMaterialParams);
}
return TEM_CHANGE_NONE;
}
S32 LLPrimTextureList::size() const
{
return mEntryList.size();

View File

@@ -39,9 +39,11 @@
#include "lluuid.h"
#include "v3color.h"
#include "v4color.h"
#include "llmaterial.h"
class LLTextureEntry;
class LLMaterialID;
// this is a list of LLTextureEntry*'s because in practice the list's elements
// are of some derived class: LLFooTextureEntry
@@ -110,6 +112,8 @@ public:
S32 setFullbright(const U8 index, const U8 t);
S32 setMediaFlags(const U8 index, const U8 media_flags);
S32 setGlow(const U8 index, const F32 glow);
S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID);
S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
S32 size() const;

View File

@@ -29,6 +29,7 @@
#include "lluuid.h"
#include "llmediaentry.h"
#include "lltextureentry.h"
#include "llmaterialid.h"
#include "llsdutil_math.h"
#include "v4color.h"
@@ -60,18 +61,24 @@ LLTextureEntry* LLTextureEntry::newTextureEntry()
//===============================================================
LLTextureEntry::LLTextureEntry()
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
{
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
{
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
{
mID = rhs.mID;
mScaleS = rhs.mScaleS;
@@ -83,6 +90,8 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
mMaterialID = rhs.mMaterialID;
mMaterial = rhs.mMaterial;
if (rhs.mMediaEntry != NULL) {
// Make a copy
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
@@ -103,6 +112,8 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
mMaterialID = rhs.mMaterialID;
mMaterial = rhs.mMaterial;
if (mMediaEntry != NULL) {
delete mMediaEntry;
}
@@ -130,6 +141,7 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of
mBump = bump;
mMediaFlags = 0x0;
mGlow = 0;
mMaterialID.clear();
setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
if (mMediaEntry != NULL) {
@@ -159,6 +171,7 @@ bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
if (mBump != rhs.mBump) return (true);
if (mMediaFlags != rhs.mMediaFlags) return (true);
if (mGlow != rhs.mGlow) return (true);
if (mMaterialID != rhs.mMaterialID) return (true);
return(false);
}
@@ -174,6 +187,7 @@ bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const
if (mBump != rhs.mBump) return (false);
if (mMediaFlags != rhs.mMediaFlags) return false;
if (mGlow != rhs.mGlow) return false;
if (mMaterialID != rhs.mMaterialID) return (false);
return(true);
}
@@ -523,6 +537,34 @@ S32 LLTextureEntry::setGlow(F32 glow)
return TEM_CHANGE_NONE;
}
S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID)
{
if ( (mMaterialID != pMaterialID) || (mMaterialUpdatePending && !mSelected) )
{
if (mSelected)
{
mMaterialUpdatePending = true;
mMaterialID = pMaterialID;
return TEM_CHANGE_NONE;
}
mMaterialUpdatePending = false;
mMaterialID = pMaterialID;
return TEM_CHANGE_TEXTURE;
}
return TEM_CHANGE_NONE;
}
S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
{
if (mSelected)
{
mMaterialUpdatePending = true;
}
mMaterial = pMaterialParams;
return TEM_CHANGE_TEXTURE;
}
void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
{
mMediaFlags |= MF_HAS_MEDIA;

View File

@@ -30,6 +30,8 @@
#include "lluuid.h"
#include "v4color.h"
#include "llsd.h"
#include "llmaterialid.h"
#include "llmaterial.h"
// These bits are used while unpacking TEM messages to tell which aspects of
// the texture entry changed.
@@ -98,6 +100,10 @@ public:
void init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump);
bool hasPendingMaterialUpdate() const { return mMaterialUpdatePending; }
bool isSelected() const { return mSelected; }
bool setSelected(bool sel) { bool prev_sel = mSelected; mSelected = sel; return prev_sel; }
// These return a TEM_ flag from above to indicate if something changed.
S32 setID (const LLUUID &tex_id);
S32 setColor(const LLColor4 &color);
@@ -121,6 +127,8 @@ public:
S32 setTexGen(U8 texGen);
S32 setMediaTexGen(U8 media);
S32 setGlow(F32 glow);
S32 setMaterialID(const LLMaterialID& pMaterialID);
S32 setMaterialParams(const LLMaterialPtr pMaterialParams);
virtual const LLUUID &getID() const { return mID; }
const LLColor4 &getColor() const { return mColor; }
@@ -139,6 +147,8 @@ public:
U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; }
U8 getMediaTexGen() const { return mMediaFlags; }
F32 getGlow() const { return mGlow; }
const LLMaterialID& getMaterialID() const { return mMaterialID; };
const LLMaterialPtr getMaterialParams() const { return mMaterial; };
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
@@ -188,11 +198,15 @@ public:
static const char* TEXTURE_MEDIA_DATA_KEY;
protected:
bool mSelected;
LLUUID mID; // Texture GUID
LLColor4 mColor;
U8 mBump; // Bump map, shiny, and fullbright
U8 mMediaFlags; // replace with web page, movie, etc.
F32 mGlow;
bool mMaterialUpdatePending;
LLMaterialID mMaterialID;
LLMaterialPtr mMaterial;
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face

View File

@@ -87,10 +87,6 @@ LLComboBox::LLComboBox(const std::string& name, const LLRect& rect, const std::s
mButton->setFont(LLFontGL::getFontSansSerifSmall());
mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
mButton->setHAlign( LLFontGL::LEFT );
if(mAllowTextEntry)
{
mButton->setRightHPad(2);
}
addChild(mButton);
@@ -914,6 +910,11 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char)
void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
{
mAllowTextEntry = allow;
if(allow)
mButton->setRightHPad(2);
else
mButton->setRightHPad(LLBUTTON_H_PAD);
mTextEntryTentative = set_tentative;
mMaxChars = max_chars;

View File

@@ -319,6 +319,7 @@ set(viewer_SOURCE_FILES
llmapresponders.cpp
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
llmaterialmgr.cpp
llmediactrl.cpp
llmediadataclient.cpp
llmediaremotectrl.cpp
@@ -832,6 +833,7 @@ set(viewer_HEADER_FILES
llmapresponders.h
llmarketplacefunctions.h
llmarketplacenotifications.h
llmaterialmgr.h
llmediactrl.h
llmediadataclient.h
llmediaremotectrl.h

View File

@@ -10421,6 +10421,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PrimMediaAutoPlayEnable</key>
<map>
<key>Comment</key>
<string>Auto play prim media when available</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PerAccountSettingsFile</key>
<map>
<key>Comment</key>

View File

@@ -52,6 +52,7 @@ typedef LLMemberListener<LLView> view_listener_t;
namespace
{
const std::string OBJ(".obj");
void save_wavefront_continued(WavefrontSaver* wfsaver, AIFilePicker* filepicker)
{
if (filepicker->hasFilename())
@@ -71,6 +72,25 @@ namespace
delete wfsaver;
}
void save_wavefront_picker(WavefrontSaver* wfsaver, std::string name)
{
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(name);
filepicker->run(boost::bind(&save_wavefront_continued, wfsaver, filepicker));
}
void save_wavefront_on_confirm(const LLSD& notification, const LLSD& response, WavefrontSaver* wfsaver, std::string name)
{
if (LLNotificationsUtil::getSelectedOption(notification, response) == 0) // 0 - Proceed, first choice
{
save_wavefront_picker(wfsaver, name);
}
else
{
delete wfsaver;
}
}
}
Wavefront::Wavefront(vert_t v, tri_t t)
@@ -129,19 +149,19 @@ Wavefront::Wavefront(LLFace* face, LLPolyMesh* mesh, const LLXform* transform, c
const U16 start = face->getGeomStart();
const U32 end = start + (mesh ? mesh->getNumVertices() : vb->getNumVerts()) - 1; //vertices
for (int i = start; i <= end; ++i)
for (U32 i = start; i <= end; ++i)
vertices.push_back(std::make_pair(getVerts[i], getCoord[i]));
if (transform) Transform(vertices, transform);
for (int i = start; i <= end; ++i)
for (U32 i = start; i <= end; ++i)
normals.push_back(getNorms[i]);
if (transform_normals) Transform(normals, transform_normals);
const U32 pcount = mesh ? mesh->getNumFaces() : (vb->getNumIndices()/3); //indices
const U16 offset = face->getIndicesStart(); //indices
for (int i = 0; i < pcount; ++i)
for (U32 i = 0; i < pcount; ++i)
{
triangles.push_back(tri(getIndices[i * 3 + offset] + start, getIndices[i * 3 + 1 + offset] + start, getIndices[i * 3 + 2 + offset] + start));
}
@@ -204,12 +224,10 @@ namespace
{
if (const LLPermissions* perms = node->mPermissions)
{
if (!(gAgentID == perms->getCreator() || (LFSimFeatureHandler::instance().simSupportsExport() && gAgentID == perms->getOwner() && perms->getMaskEveryone() & PERM_EXPORT)))
if (gAgentID == perms->getCreator() || (LFSimFeatureHandler::instance().simSupportsExport() && gAgentID == perms->getOwner() && perms->getMaskEveryone() & PERM_EXPORT))
{
static const LLCachedControl<bool> notify("OBJExportNotifyFailed", false);
if (notify) LLNotificationsUtil::add("WavefrontExportPartial", LLSD().with("OBJECT", node->mName));
return true;
}
else return true;
}
return false;
}
@@ -221,10 +239,14 @@ namespace
{
WavefrontSaver* wfsaver = new WavefrontSaver; // deleted in callback
wfsaver->offset = -selection->getFirstRootObject()->getRenderPosition();
S32 total = 0;
S32 included = 0;
for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end(); ++iter)
{
total++;
LLSelectNode* node = *iter;
if (!can_export_node(node)) continue;
included++;
wfsaver->Add(node->getObject());
}
if (wfsaver->obj_v.empty())
@@ -235,9 +257,16 @@ namespace
return true;
}
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(selection->getFirstNode()->mName.c_str()+OBJ);
filepicker->run(boost::bind(&save_wavefront_continued, wfsaver, filepicker));
if (total != included)
{
LLSD args;
args["TOTAL"] = total;
args["FAILED"] = total - included;
LLNotificationsUtil::add("WavefrontExportPartial", args, LLSD(), boost::bind(&save_wavefront_on_confirm, _1, _2, wfsaver, selection->getFirstNode()->mName.c_str() + OBJ));
return true;
}
save_wavefront_picker(wfsaver, selection->getFirstNode()->mName.c_str() + OBJ);
}
return true;
}

View File

@@ -4439,7 +4439,7 @@ void LLAgent::requestLeaveGodMode()
sendReliableMessage();
}
extern void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value);
extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
extern std::string get_sequential_numbered_file_name(const std::string& prefix,
const std::string& suffix);
@@ -4465,7 +4465,7 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
if (appearance_version_param)
{
F32 value = appearance_version_param->getWeight();
dump_visual_param(file, appearance_version_param, value);
dump_visual_param(outfile, appearance_version_param, value);
}
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();

View File

@@ -140,6 +140,17 @@ void LLDrawPoolAvatar::prerender()
{
sBufferUsage = GL_STREAM_DRAW_ARB;
}
if (!mDrawFace.empty())
{
const LLFace *facep = mDrawFace[0];
if (facep && facep->getDrawable())
{
LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
updateRiggedVertexBuffers(avatarp);
}
}
}
LLMatrix4& LLDrawPoolAvatar::getModelView()
@@ -1546,7 +1557,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar)
{
updateRiggedVertexBuffers(avatar);
renderRigged(avatar, RIGGED_DEFERRED_SIMPLE);
}
@@ -1610,7 +1620,6 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
{
updateRiggedVertexBuffers(avatar);
renderRigged(avatar, RIGGED_SIMPLE);
}

View File

@@ -1072,6 +1072,12 @@ bool LLFace::canRenderAsMask()
return false;
}
LLMaterial* mat = te->getMaterialParams();
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
{
return false;
}
static const LLCachedControl<bool> use_rmse_auto_mask("SHUseRMSEAutoMask",false);
static const LLCachedControl<F32> auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f);
if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha

View File

@@ -81,6 +81,7 @@
#include "llappearancemgr.h"
#include "statemachine/aifilepicker.h"
#include "llxmltree.h"
using namespace LLAvatarAppearanceDefines;
@@ -297,7 +298,7 @@ void LLFloaterCustomize::onBtnImport()
{
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_XML);
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnImport_continued, filepicker));
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnImport_continued, this, filepicker));
}
void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
@@ -308,59 +309,143 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
return;
}
const std::string filename = filepicker->getFilename();
// Find the editted wearable.
LLPanelEditWearable* panel_edit_wearable = getCurrentWearablePanel();
LLViewerWearable* edit_wearable = panel_edit_wearable->getWearable();
FILE* fp = LLFile::fopen(filename, "rb");
std::string const filename = filepicker->getFilename();
//char text_buffer[2048]; /* Flawfinder: ignore */
S32 c;
S32 typ;
S32 count;
S32 param_id=0;
F32 param_weight=0;
S32 fields_read;
for( S32 i=0; i < LLWearableType::WT_COUNT; i++ )
LLXmlTree xml;
BOOL success = xml.parseFile(filename, FALSE);
if (!success)
{
fields_read = fscanf( fp, "type %d\n", &typ);
if( fields_read != 1 )
{
llwarns << "Bad asset type: early end of file" << llendl;
return;
}
llwarns << "Could not read or parse wearable import file \"" << filename << "\"." << llendl;
return;
}
LLXmlTreeNode* root = xml.getRoot();
if (!root)
{
llwarns << "No root node found in wearable import file: " << filename << llendl;
return;
}
fields_read = fscanf( fp, "parameters %d\n", &count);
if( fields_read != 1 )
{
llwarns << "Bad parameters : early end of file" << llendl;
return;
}
for(c=0;c<count;c++)
{
fields_read = fscanf( fp, "%d %f\n", &param_id, &param_weight );
if( fields_read != 2 )
{
llwarns << "Bad parameters list: early end of file" << llendl;
return;
}
gAgentAvatarp->setVisualParamWeight( param_id, param_weight, TRUE);
gAgentAvatarp->updateVisualParams();
}
//-------------------------------------------------------------------------
// <linden_genepool version="1.0"> (root)
//-------------------------------------------------------------------------
if (!root->hasName("linden_genepool"))
{
llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl;
return;
}
static LLStdStringHandle const version_string = LLXmlTree::addAttributeString("version");
std::string version;
if (!root->getFastAttributeString(version_string, version) || (version != "1.0"))
{
llwarns << "Invalid linden_genepool version: " << version << " in file: " << filename << llendl;
return;
}
fclose(fp);
return;
//-------------------------------------------------------------------------
// <archetype name="???">
//-------------------------------------------------------------------------
LLXmlTreeNode* archetype_node = root->getChildByName("archetype");
if (!archetype_node)
{
llwarns << "No archetype in wearable import file: " << filename << llendl;
return;
}
// Parse the XML content.
static LLStdStringHandle const id_string = LLXmlTree::addAttributeString("id");
static LLStdStringHandle const value_string = LLXmlTree::addAttributeString("value");
static LLStdStringHandle const te_string = LLXmlTree::addAttributeString("te");
static LLStdStringHandle const uuid_string = LLXmlTree::addAttributeString("uuid");
for(LLXmlTreeNode* child = archetype_node->getFirstChild(); child; child = archetype_node->getNextChild())
{
if (child->hasName("param"))
{
std::string id_s;
U32 id;
std::string value_s;
F32 value;
if (!child->getFastAttributeString(id_string, id_s) || !LLStringUtil::convertToU32(id_s, id) ||
!child->getFastAttributeString(value_string, value_s) || !LLStringUtil::convertToF32(value_s, value))
{
llwarns << "Possible syntax error or corruption for <param id=... value=... /> node in " << filename << llendl;
continue;
}
LLVisualParam* visual_param = edit_wearable->getVisualParam(id);
if (visual_param)
{
visual_param->setWeight(value, FALSE);
}
}
else if (child->hasName("texture"))
{
std::string te_s;
S32 te;
std::string uuid_s;
LLUUID uuid;
if (!child->getFastAttributeString(te_string, te_s) || !LLStringUtil::convertToS32(te_s, te) || te < 0 || te >= TEX_NUM_INDICES ||
!child->getFastAttributeString(uuid_string, uuid_s) || !uuid.set(uuid_s, TRUE))
{
llwarns << "Possible syntax error or corruption for <texture te=... uuid=... /> node in " << filename << llendl;
continue;
}
ETextureIndex te_index = (ETextureIndex)te;
LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index);
if (te_wearable_type == edit_wearable->getType())
{
panel_edit_wearable->setNewImageID(te_index, uuid);
}
}
}
edit_wearable->writeToAvatar(gAgentAvatarp);
gAgentAvatarp->updateVisualParams();
panel_edit_wearable->updateScrollingPanelUI();
}
// reX: new function
void LLFloaterCustomize::onBtnExport()
{
// Find the editted wearable.
LLPanelEditWearable* panel_edit_wearable = getCurrentWearablePanel();
LLViewerWearable* edit_wearable = panel_edit_wearable->getWearable();
U32 edit_index = panel_edit_wearable->getIndex();
std::string const& name = edit_wearable->getName();
// Determine if the currently selected wearable is modifiable.
LLWearableType::EType edit_type = getCurrentWearableType();
bool is_modifiable = false;
LLViewerWearable* old_wearable = gAgentWearables.getViewerWearable(edit_type, edit_index);
if (old_wearable)
{
LLViewerInventoryItem* item = gInventory.getItem(old_wearable->getItemID());
if (item)
{
LLPermissions const& perm = item->getPermissions();
// Modifiable means the user can see the sliders and type them over into a file anyway.
is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
}
}
if (!is_modifiable)
{
// We should never get here, because in that case the Export button is disabled.
llwarns << "Cannot export current wearable \"" << name << "\" of type " << (int)edit_type << "because user lacks modify permissions." << llendl;
return;
}
std::string file_name = edit_wearable->getName() + "_" + edit_wearable->getTypeName() + "?000.xml";
std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("", FFSAVE_XML);
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnExport_continued, filepicker));
filepicker->open(file_name, FFSAVE_XML, default_path, "archetype");
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnExport_continued, edit_wearable, filepicker));
}
void LLFloaterCustomize::onBtnExport_continued(AIFilePicker* filepicker)
//static
void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable, AIFilePicker* filepicker)
{
if (!filepicker->hasFilename())
{
@@ -368,62 +453,17 @@ void LLFloaterCustomize::onBtnExport_continued(AIFilePicker* filepicker)
return;
}
LLViewerInventoryItem* item;
BOOL is_modifiable;
const std::string filename = filepicker->getFilename();
FILE* fp = LLFile::fopen(filename, "wb");
for( S32 i=0; i < LLWearableType::WT_COUNT; i++ )
LLAPRFile outfile;
outfile.open(filepicker->getFilename(), LL_APR_WB);
if (!outfile.getFileHandle())
{
is_modifiable = FALSE;
LLViewerWearable* old_wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)i, 0); // TODO: MULTI-WEARABLE
if( old_wearable )
{
item = gInventory.getItem(old_wearable->getItemID());
if(item)
{
const LLPermissions& perm = item->getPermissions();
is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
}
}
if (is_modifiable)
{
old_wearable->FileExportParams(fp);
}
if (!is_modifiable)
{
fprintf( fp, "type %d\n",i);
fprintf( fp, "parameters 0\n");
}
}
llwarns << "Could not open \"" << filepicker->getFilename() << "\" for writing." << llendl;
return;
}
for( S32 i=0; i < LLWearableType::WT_COUNT; i++ )
{
is_modifiable = FALSE;
LLViewerWearable* old_wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)i, 0); // TODO: MULTI-WEARABLE
if( old_wearable )
{
item = gInventory.getItem(old_wearable->getItemID());
if(item)
{
const LLPermissions& perm = item->getPermissions();
is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
}
}
if (is_modifiable)
{
old_wearable->FileExportTextures(fp);
}
if (!is_modifiable)
{
fprintf( fp, "type %d\n",i);
fprintf( fp, "textures 0\n");
}
}
fclose(fp);
LLVOAvatar::dumpArchetypeXML_header(outfile);
edit_wearable->archetypeExport(outfile);
LLVOAvatar::dumpArchetypeXML_footer(outfile);
}
void LLFloaterCustomize::onBtnOk()

View File

@@ -125,9 +125,9 @@ private:
void onBtnOk();
void onBtnMakeOutfit();
void onBtnImport();
static void onBtnImport_continued(AIFilePicker* filepicker);
void onBtnImport_continued(AIFilePicker* filepicker);
void onBtnExport();
static void onBtnExport_continued(AIFilePicker* filepicker);
static void onBtnExport_continued(LLViewerWearable* edit_wearable, AIFilePicker* filepicker);
void onTabChanged( const LLSD& param );
bool onTabPrecommit( LLUICtrl* ctrl, const LLSD& param );
bool onSaveDialog(const LLSD& notification, const LLSD& response);

View File

@@ -0,0 +1,793 @@
/**
* @file llmaterialmgr.cpp
* @brief Material manager
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llsdserialize.h"
#include "llsdutil.h"
#include "llagent.h"
#include "llcallbacklist.h"
#include "llmaterialmgr.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llworld.h"
/**
* Materials cap parameters
*/
#define MATERIALS_CAPABILITY_NAME "RenderMaterials"
#define MATERIALS_CAP_ZIP_FIELD "Zipped"
#define MATERIALS_CAP_FULL_PER_FACE_FIELD "FullMaterialsPerFace"
#define MATERIALS_CAP_FACE_FIELD "Face"
#define MATERIALS_CAP_MATERIAL_FIELD "Material"
#define MATERIALS_CAP_OBJECT_ID_FIELD "ID"
#define MATERIALS_CAP_MATERIAL_ID_FIELD "MaterialID"
#define MATERIALS_GET_MAX_ENTRIES 50
#define MATERIALS_GET_TIMEOUT (60.f * 20)
#define MATERIALS_POST_MAX_ENTRIES 50
#define MATERIALS_POST_TIMEOUT (60.f * 5)
#define MATERIALS_PUT_THROTTLE_SECS 1.f
#define MATERIALS_PUT_MAX_ENTRIES 50
/**
* LLMaterialsResponder helper class
*/
extern AIHTTPTimeoutPolicy materialsResponder_timeout;
class LLMaterialsResponder : public LLHTTPClient::ResponderWithResult
{
public:
typedef boost::function<void (bool, const LLSD&)> CallbackFunction;
LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
virtual ~LLMaterialsResponder();
virtual void result(const LLSD& pContent);
virtual void error(U32 pStatus, const std::string& pReason);
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return materialsResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLMaterialsResponder"; }
private:
std::string mMethod;
std::string mCapabilityURL;
CallbackFunction mCallback;
};
LLMaterialsResponder::LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback)
: LLHTTPClient::ResponderWithResult()
, mMethod(pMethod)
, mCapabilityURL(pCapabilityURL)
, mCallback(pCallback)
{
}
LLMaterialsResponder::~LLMaterialsResponder()
{
}
void LLMaterialsResponder::result(const LLSD& pContent)
{
LL_DEBUGS("Materials") << LL_ENDL;
mCallback(true, pContent);
}
void LLMaterialsResponder::error(U32 pStatus, const std::string& pReason)
{
LL_WARNS("Materials")
<< "\n--------------------------------------------------------------------------\n"
<< mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
<< "'\n with url '" << mCapabilityURL << "' because " << pReason
<< "\n--------------------------------------------------------------------------"
<< LL_ENDL;
LLSD emptyResult;
mCallback(false, emptyResult);
}
/**
* LLMaterialMgr class
*/
LLMaterialMgr::LLMaterialMgr()
{
mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(LLMaterialID::null, LLMaterialPtr(NULL)));
gIdleCallbacks.addFunction(&LLMaterialMgr::onIdle, NULL);
LLWorld::instance().setRegionRemovedCallback(boost::bind(&LLMaterialMgr::onRegionRemoved, this, _1));
}
LLMaterialMgr::~LLMaterialMgr()
{
gIdleCallbacks.deleteFunction(&LLMaterialMgr::onIdle, NULL);
}
bool LLMaterialMgr::isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const
{
get_pending_map_t::const_iterator itPending = mGetPending.find(pending_material_t(region_id, material_id));
return (mGetPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + MATERIALS_POST_TIMEOUT);
}
void LLMaterialMgr::markGetPending(const LLUUID& region_id, const LLMaterialID& material_id)
{
get_pending_map_t::iterator itPending = mGetPending.find(pending_material_t(region_id, material_id));
if (mGetPending.end() == itPending)
{
mGetPending.insert(std::pair<pending_material_t, F64>(pending_material_t(region_id, material_id), LLFrameTimer::getTotalSeconds()));
}
else
{
itPending->second = LLFrameTimer::getTotalSeconds();
}
}
const LLMaterialPtr LLMaterialMgr::get(const LLUUID& region_id, const LLMaterialID& material_id)
{
LL_DEBUGS("Materials") << "region " << region_id << " material id " << material_id << LL_ENDL;
LLMaterialPtr material;
material_map_t::const_iterator itMaterial = mMaterials.find(material_id);
if (mMaterials.end() != itMaterial)
{
material = itMaterial->second;
LL_DEBUGS("Materials") << " found material " << LL_ENDL;
}
else
{
if (!isGetPending(region_id, material_id))
{
LL_DEBUGS("Materials") << " material pending " << material_id << LL_ENDL;
get_queue_t::iterator itQueue = mGetQueue.find(region_id);
if (mGetQueue.end() == itQueue)
{
LL_DEBUGS("Materials") << "mGetQueue add region " << region_id << " pending " << material_id << LL_ENDL;
std::pair<get_queue_t::iterator, bool> ret = mGetQueue.insert(std::pair<LLUUID, material_queue_t>(region_id, material_queue_t()));
itQueue = ret.first;
}
itQueue->second.insert(material_id);
markGetPending(region_id, material_id);
}
LL_DEBUGS("Materials") << " returning empty material " << LL_ENDL;
material = LLMaterialPtr();
}
return material;
}
boost::signals2::connection LLMaterialMgr::get(const LLUUID& region_id, const LLMaterialID& material_id, LLMaterialMgr::get_callback_t::slot_type cb)
{
boost::signals2::connection connection;
material_map_t::const_iterator itMaterial = mMaterials.find(material_id);
if (itMaterial != mMaterials.end())
{
LL_DEBUGS("Materials") << "region " << region_id << " found materialid " << material_id << LL_ENDL;
get_callback_t signal;
signal.connect(cb);
signal(material_id, itMaterial->second);
connection = boost::signals2::connection();
}
else
{
if (!isGetPending(region_id, material_id))
{
get_queue_t::iterator itQueue = mGetQueue.find(region_id);
if (mGetQueue.end() == itQueue)
{
LL_DEBUGS("Materials") << "mGetQueue inserting region "<<region_id << LL_ENDL;
std::pair<get_queue_t::iterator, bool> ret = mGetQueue.insert(std::pair<LLUUID, material_queue_t>(region_id, material_queue_t()));
itQueue = ret.first;
}
LL_DEBUGS("Materials") << "adding material id " << material_id << LL_ENDL;
itQueue->second.insert(material_id);
markGetPending(region_id, material_id);
}
get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id);
if (itCallback == mGetCallbacks.end())
{
std::pair<get_callback_map_t::iterator, bool> ret = mGetCallbacks.insert(std::pair<LLMaterialID, get_callback_t*>(material_id, new get_callback_t()));
itCallback = ret.first;
}
connection = itCallback->second->connect(cb);;
}
return connection;
}
boost::signals2::connection LLMaterialMgr::getTE(const LLUUID& region_id, const LLMaterialID& material_id, U32 te, LLMaterialMgr::get_callback_te_t::slot_type cb)
{
boost::signals2::connection connection;
material_map_t::const_iterator itMaterial = mMaterials.find(material_id);
if (itMaterial != mMaterials.end())
{
LL_DEBUGS("Materials") << "region " << region_id << " found materialid " << material_id << LL_ENDL;
get_callback_te_t signal;
signal.connect(cb);
signal(material_id, itMaterial->second, te);
connection = boost::signals2::connection();
}
else
{
if (!isGetPending(region_id, material_id))
{
get_queue_t::iterator itQueue = mGetQueue.find(region_id);
if (mGetQueue.end() == itQueue)
{
LL_DEBUGS("Materials") << "mGetQueue inserting region "<<region_id << LL_ENDL;
std::pair<get_queue_t::iterator, bool> ret = mGetQueue.insert(std::pair<LLUUID, material_queue_t>(region_id, material_queue_t()));
itQueue = ret.first;
}
LL_DEBUGS("Materials") << "adding material id " << material_id << LL_ENDL;
itQueue->second.insert(material_id);
markGetPending(region_id, material_id);
}
TEMaterialPair te_mat_pair;
te_mat_pair.te = te;
te_mat_pair.materialID = material_id;
get_callback_te_map_t::iterator itCallback = mGetTECallbacks.find(te_mat_pair);
if (itCallback == mGetTECallbacks.end())
{
std::pair<get_callback_te_map_t::iterator, bool> ret = mGetTECallbacks.insert(std::pair<TEMaterialPair, get_callback_te_t*>(te_mat_pair, new get_callback_te_t()));
itCallback = ret.first;
}
connection = itCallback->second->connect(cb);
}
return connection;
}
bool LLMaterialMgr::isGetAllPending(const LLUUID& region_id) const
{
getall_pending_map_t::const_iterator itPending = mGetAllPending.find(region_id);
return (mGetAllPending.end() != itPending) && (LLFrameTimer::getTotalSeconds() < itPending->second + MATERIALS_GET_TIMEOUT);
}
void LLMaterialMgr::getAll(const LLUUID& region_id)
{
if (!isGetAllPending(region_id))
{
LL_DEBUGS("Materials") << "queuing for region " << region_id << LL_ENDL;
mGetAllQueue.insert(region_id);
}
else
{
LL_DEBUGS("Materials") << "already pending for region " << region_id << LL_ENDL;
}
}
boost::signals2::connection LLMaterialMgr::getAll(const LLUUID& region_id, LLMaterialMgr::getall_callback_t::slot_type cb)
{
if (!isGetAllPending(region_id))
{
mGetAllQueue.insert(region_id);
}
getall_callback_map_t::iterator itCallback = mGetAllCallbacks.find(region_id);
if (mGetAllCallbacks.end() == itCallback)
{
std::pair<getall_callback_map_t::iterator, bool> ret = mGetAllCallbacks.insert(std::pair<LLUUID, getall_callback_t*>(region_id, new getall_callback_t()));
itCallback = ret.first;
}
return itCallback->second->connect(cb);;
}
void LLMaterialMgr::put(const LLUUID& object_id, const U8 te, const LLMaterial& material)
{
put_queue_t::iterator itQueue = mPutQueue.find(object_id);
if (mPutQueue.end() == itQueue)
{
LL_DEBUGS("Materials") << "mPutQueue insert object " << object_id << LL_ENDL;
mPutQueue.insert(std::pair<LLUUID, facematerial_map_t>(object_id, facematerial_map_t()));
itQueue = mPutQueue.find(object_id);
}
facematerial_map_t::iterator itFace = itQueue->second.find(te);
if (itQueue->second.end() == itFace)
{
itQueue->second.insert(std::pair<U8, LLMaterial>(te, material));
}
else
{
itFace->second = material;
}
}
void LLMaterialMgr::remove(const LLUUID& object_id, const U8 te)
{
put(object_id, te, LLMaterial::null);
}
const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data)
{
LL_DEBUGS("Materials") << "region " << region_id << " material id " << material_id << LL_ENDL;
material_map_t::const_iterator itMaterial = mMaterials.find(material_id);
if (mMaterials.end() == itMaterial)
{
LL_DEBUGS("Materials") << "new material" << LL_ENDL;
LLMaterialPtr newMaterial(new LLMaterial(material_data));
std::pair<material_map_t::const_iterator, bool> ret = mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(material_id, newMaterial));
itMaterial = ret.first;
}
// we may have cleared our queues on leaving a region before we recv'd our
// update for this material...too late now!
//
if (isGetPending(region_id, material_id))
{
TEMaterialPair te_mat_pair;
te_mat_pair.materialID = material_id;
U32 i = 0;
while (i < LLTEContents::MAX_TES)
{
te_mat_pair.te = i++;
get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair);
if (itCallbackTE != mGetTECallbacks.end())
{
(*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te);
delete itCallbackTE->second;
mGetTECallbacks.erase(itCallbackTE);
}
}
get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id);
if (itCallback != mGetCallbacks.end())
{
(*itCallback->second)(material_id, itMaterial->second);
delete itCallback->second;
mGetCallbacks.erase(itCallback);
}
}
mGetPending.erase(pending_material_t(region_id, material_id));
return itMaterial->second;
}
void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUID& region_id)
{
if (!success)
{
// *TODO: is there any kind of error handling we can do here?
LL_WARNS("Materials")<< "failed"<<LL_ENDL;
return;
}
llassert(content.isMap());
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
LLSD response_data;
if (!unzip_llsd(response_data, content_stream, content_binary.size()))
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content" << LL_ENDL;
return;
}
llassert(response_data.isArray());
LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL;
for (LLSD::array_const_iterator itMaterial = response_data.beginArray(); itMaterial != response_data.endArray(); ++itMaterial)
{
const LLSD& material_data = *itMaterial;
llassert(material_data.isMap());
llassert(material_data.has(MATERIALS_CAP_OBJECT_ID_FIELD));
llassert(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].isBinary());
LLMaterialID material_id(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].asBinary());
llassert(material_data.has(MATERIALS_CAP_MATERIAL_FIELD));
llassert(material_data[MATERIALS_CAP_MATERIAL_FIELD].isMap());
setMaterial(region_id, material_id, material_data[MATERIALS_CAP_MATERIAL_FIELD]);
}
}
void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LLUUID& region_id)
{
if (!success)
{
// *TODO: is there any kind of error handling we can do here?
LL_WARNS("Materials")<< "failed"<<LL_ENDL;
return;
}
llassert(content.isMap());
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
LLSD response_data;
if (!unzip_llsd(response_data, content_stream, content_binary.size()))
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content" << LL_ENDL;
return;
}
get_queue_t::iterator itQueue = mGetQueue.find(region_id);
material_map_t materials;
llassert(response_data.isArray());
LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL;
for (LLSD::array_const_iterator itMaterial = response_data.beginArray(); itMaterial != response_data.endArray(); ++itMaterial)
{
const LLSD& material_data = *itMaterial;
llassert(material_data.isMap());
llassert(material_data.has(MATERIALS_CAP_OBJECT_ID_FIELD));
llassert(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].isBinary());
LLMaterialID material_id(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].asBinary());
if (mGetQueue.end() != itQueue)
{
itQueue->second.erase(material_id);
}
llassert(material_data.has(MATERIALS_CAP_MATERIAL_FIELD));
llassert(material_data[MATERIALS_CAP_MATERIAL_FIELD].isMap());
LLMaterialPtr material = setMaterial(region_id, material_id, material_data[MATERIALS_CAP_MATERIAL_FIELD]);
materials[material_id] = material;
}
getall_callback_map_t::iterator itCallback = mGetAllCallbacks.find(region_id);
if (itCallback != mGetAllCallbacks.end())
{
(*itCallback->second)(region_id, materials);
delete itCallback->second;
mGetAllCallbacks.erase(itCallback);
}
if ( (mGetQueue.end() != itQueue) && (itQueue->second.empty()) )
{
mGetQueue.erase(itQueue);
}
LL_DEBUGS("Materials")<< "recording that getAll has been done for region id " << region_id << LL_ENDL;
mGetAllRequested.insert(region_id); // prevents subsequent getAll requests for this region
mGetAllPending.erase(region_id); // Invalidates region_id
}
void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
{
if (!success)
{
// *TODO: is there any kind of error handling we can do here?
LL_WARNS("Materials")<< "failed"<<LL_ENDL;
return;
}
llassert(content.isMap());
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
LLSD response_data;
if (!unzip_llsd(response_data, content_stream, content_binary.size()))
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content" << LL_ENDL;
return;
}
else
{
llassert(response_data.isArray());
LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL;
for (LLSD::array_const_iterator faceIter = response_data.beginArray(); faceIter != response_data.endArray(); ++faceIter)
{
# ifndef LL_RELEASE_FOR_DOWNLOAD
const LLSD& face_data = *faceIter; // conditional to avoid unused variable warning
# endif
llassert(face_data.isMap());
llassert(face_data.has(MATERIALS_CAP_OBJECT_ID_FIELD));
llassert(face_data[MATERIALS_CAP_OBJECT_ID_FIELD].isInteger());
// U32 local_id = face_data[MATERIALS_CAP_OBJECT_ID_FIELD].asInteger();
llassert(face_data.has(MATERIALS_CAP_FACE_FIELD));
llassert(face_data[MATERIALS_CAP_FACE_FIELD].isInteger());
// S32 te = face_data[MATERIALS_CAP_FACE_FIELD].asInteger();
llassert(face_data.has(MATERIALS_CAP_MATERIAL_ID_FIELD));
llassert(face_data[MATERIALS_CAP_MATERIAL_ID_FIELD].isBinary());
// LLMaterialID material_id(face_data[MATERIALS_CAP_MATERIAL_ID_FIELD].asBinary());
// *TODO: do we really still need to process this?
}
}
}
static LLFastTimer::DeclareTimer FTM_MATERIALS_IDLE("Materials");
void LLMaterialMgr::onIdle(void*)
{
LLFastTimer t(FTM_MATERIALS_IDLE);
LLMaterialMgr* instancep = LLMaterialMgr::getInstance();
if (!instancep->mGetQueue.empty())
{
instancep->processGetQueue();
}
if (!instancep->mGetAllQueue.empty())
{
instancep->processGetAllQueue();
}
static LLFrameTimer mPutTimer;
if ( (!instancep->mPutQueue.empty()) && (mPutTimer.hasExpired()) )
{
instancep->processPutQueue();
mPutTimer.reset(MATERIALS_PUT_THROTTLE_SECS);
}
}
void LLMaterialMgr::processGetQueue()
{
get_queue_t::iterator loopRegionQueue = mGetQueue.begin();
while (mGetQueue.end() != loopRegionQueue)
{
get_queue_t::iterator itRegionQueue = loopRegionQueue++;
const LLUUID& region_id = itRegionQueue->first;
if (isGetAllPending(region_id))
{
continue;
}
const LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
if (!regionp)
{
LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
mGetQueue.erase(itRegionQueue);
continue;
}
else if (!regionp->capabilitiesReceived())
{
continue;
}
else if (mGetAllRequested.end() == mGetAllRequested.find(region_id))
{
LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL;
getAll(region_id);
continue;
}
const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
if (capURL.empty())
{
LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
<< "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL;
mGetQueue.erase(itRegionQueue);
continue;
}
LLSD materialsData = LLSD::emptyArray();
material_queue_t& materials = itRegionQueue->second;
material_queue_t::iterator loopMaterial = materials.begin();
while ( (materials.end() != loopMaterial) && (materialsData.size() <= MATERIALS_GET_MAX_ENTRIES) )
{
material_queue_t::iterator itMaterial = loopMaterial++;
materialsData.append((*itMaterial).asLLSD());
materials.erase(itMaterial);
markGetPending(region_id, *itMaterial);
}
if (materials.empty())
{
mGetQueue.erase(itRegionQueue);
}
std::string materialString = zip_llsd(materialsData);
S32 materialSize = materialString.size();
if (materialSize <= 0)
{
LL_ERRS("Materials") << "cannot zip LLSD binary content" << LL_ENDL;
return;
}
LLSD::Binary materialBinary;
materialBinary.resize(materialSize);
memcpy(materialBinary.data(), materialString.data(), materialSize);
LLSD postData = LLSD::emptyMap();
postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id));
LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials."
<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
LLHTTPClient::post(capURL, postData, materialsResponder);
}
}
void LLMaterialMgr::processGetAllQueue()
{
getall_queue_t::iterator loopRegion = mGetAllQueue.begin();
while (mGetAllQueue.end() != loopRegion)
{
getall_queue_t::iterator itRegion = loopRegion++;
const LLUUID& region_id = *itRegion;
LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
if (regionp == NULL)
{
LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
clearGetQueues(region_id); // Invalidates region_id
continue;
}
else if (!regionp->capabilitiesReceived())
{
continue;
}
std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
if (capURL.empty())
{
LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
<< "' is not defined on the current region '" << regionp->getName() << "'" << LL_ENDL;
clearGetQueues(region_id); // Invalidates region_id
continue;
}
LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion));
LLHTTPClient::get(capURL, materialsResponder);
mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
mGetAllQueue.erase(itRegion); // Invalidates region_id
}
}
void LLMaterialMgr::processPutQueue()
{
typedef std::map<const LLViewerRegion*, LLSD> regionput_request_map;
regionput_request_map requests;
put_queue_t::iterator loopQueue = mPutQueue.begin();
while (mPutQueue.end() != loopQueue)
{
put_queue_t::iterator itQueue = loopQueue++;
const LLUUID& object_id = itQueue->first;
const LLViewerObject* objectp = gObjectList.findObject(object_id);
if ( (!objectp) || (!objectp->getRegion()) )
{
LL_WARNS("Materials") << "Object or object region is NULL" << LL_ENDL;
mPutQueue.erase(itQueue);
continue;
}
const LLViewerRegion* regionp = objectp->getRegion();
if (!regionp->capabilitiesReceived())
{
continue;
}
LLSD& facesData = requests[regionp];
facematerial_map_t& face_map = itQueue->second;
facematerial_map_t::iterator itFace = face_map.begin();
while ( (face_map.end() != itFace) && (facesData.size() < MATERIALS_GET_MAX_ENTRIES) )
{
LLSD faceData = LLSD::emptyMap();
faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first);
faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID());
if (!itFace->second.isNull())
{
faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD();
}
facesData.append(faceData);
face_map.erase(itFace++);
}
if (face_map.empty())
{
mPutQueue.erase(itQueue);
}
}
for (regionput_request_map::const_iterator itRequest = requests.begin(); itRequest != requests.end(); ++itRequest)
{
std::string capURL = itRequest->first->getCapability(MATERIALS_CAPABILITY_NAME);
if (capURL.empty())
{
LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
<< "' is not defined on region '" << itRequest->first->getName() << "'" << LL_ENDL;
continue;
}
LLSD materialsData = LLSD::emptyMap();
materialsData[MATERIALS_CAP_FULL_PER_FACE_FIELD] = itRequest->second;
std::string materialString = zip_llsd(materialsData);
S32 materialSize = materialString.size();
if (materialSize > 0)
{
LLSD::Binary materialBinary;
materialBinary.resize(materialSize);
memcpy(materialBinary.data(), materialString.data(), materialSize);
LLSD putData = LLSD::emptyMap();
putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2));
LLHTTPClient::put(capURL, putData, materialsResponder);
}
else
{
LL_ERRS("debugMaterials") << "cannot zip LLSD binary content" << LL_ENDL;
}
}
}
void LLMaterialMgr::clearGetQueues(const LLUUID& region_id)
{
mGetQueue.erase(region_id);
for (get_pending_map_t::iterator itPending = mGetPending.begin(); itPending != mGetPending.end();)
{
if (region_id == itPending->first.first)
{
mGetPending.erase(itPending++);
}
else
{
++itPending;
}
}
mGetAllQueue.erase(region_id);
mGetAllRequested.erase(region_id);
mGetAllPending.erase(region_id);
mGetAllCallbacks.erase(region_id);
}
void LLMaterialMgr::onRegionRemoved(LLViewerRegion* regionp)
{
clearGetQueues(regionp->getRegionID());
// Put doesn't need clearing: objects that can't be found will clean up in processPutQueue()
}

View File

@@ -0,0 +1,130 @@
/**
* @file llmaterialmgr.h
* @brief Material manager
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLMATERIALMGR_H
#define LL_LLMATERIALMGR_H
#include "llmaterial.h"
#include "llmaterialid.h"
#include "llsingleton.h"
class LLViewerRegion;
class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
{
friend class LLSingleton<LLMaterialMgr>;
protected:
LLMaterialMgr();
virtual ~LLMaterialMgr();
public:
typedef std::map<LLMaterialID, LLMaterialPtr> material_map_t;
typedef boost::signals2::signal<void (const LLMaterialID&, const LLMaterialPtr)> get_callback_t;
const LLMaterialPtr get(const LLUUID& region_id, const LLMaterialID& material_id);
boost::signals2::connection get(const LLUUID& region_id, const LLMaterialID& material_id, get_callback_t::slot_type cb);
typedef boost::signals2::signal<void (const LLMaterialID&, const LLMaterialPtr, U32 te)> get_callback_te_t;
boost::signals2::connection getTE(const LLUUID& region_id, const LLMaterialID& material_id, U32 te, get_callback_te_t::slot_type cb);
typedef boost::signals2::signal<void (const LLUUID&, const material_map_t&)> getall_callback_t;
void getAll(const LLUUID& region_id);
boost::signals2::connection getAll(const LLUUID& region_id, getall_callback_t::slot_type cb);
void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);
void remove(const LLUUID& object_id, const U8 te);
protected:
void clearGetQueues(const LLUUID& region_id);
bool isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const;
bool isGetAllPending(const LLUUID& region_id) const;
void markGetPending(const LLUUID& region_id, const LLMaterialID& material_id);
const LLMaterialPtr setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data);
static void onIdle(void*);
void processGetQueue();
void onGetResponse(bool success, const LLSD& content, const LLUUID& region_id);
void processGetAllQueue();
void onGetAllResponse(bool success, const LLSD& content, const LLUUID& region_id);
void processPutQueue();
void onPutResponse(bool success, const LLSD& content);
void onRegionRemoved(LLViewerRegion* regionp);
protected:
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
get_queue_t mGetQueue;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
typedef std::map<const pending_material_t, F64> get_pending_map_t;
get_pending_map_t mGetPending;
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
get_callback_map_t mGetCallbacks;
// struct for TE-specific material ID query
class TEMaterialPair
{
public:
U32 te;
LLMaterialID materialID;
bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
};
friend inline bool operator<(
const LLMaterialMgr::TEMaterialPair& lhs,
const LLMaterialMgr::TEMaterialPair& rhs)
{
return (lhs.te < rhs.te) ? TRUE :
(lhs.materialID < rhs.materialID);
}
struct TEMaterialPairHasher
{
enum { bucket_size = 8 };
size_t operator()(const TEMaterialPair& key_value) const { return *((size_t*)key_value.materialID.get()); } // cheesy, but effective
bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
};
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
get_callback_te_map_t mGetTECallbacks;
typedef std::set<LLUUID> getall_queue_t;
getall_queue_t mGetAllQueue;
getall_queue_t mGetAllRequested;
typedef std::map<LLUUID, F64> getall_pending_map_t;
getall_pending_map_t mGetAllPending;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
getall_callback_map_t mGetAllCallbacks;
typedef std::map<U8, LLMaterial> facematerial_map_t;
typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
put_queue_t mPutQueue;
material_map_t mMaterials;
};
#endif // LL_LLMATERIALMGR_H

View File

@@ -953,22 +953,8 @@ void LLPanelEditWearable::setWearableIndex(S32 index)
if(mActiveModal)
mActiveModal->close();
U32 perm_mask = wearable ? PERM_NONE : PERM_ALL;
BOOL is_complete = wearable ? FALSE : TRUE;
if(wearable)
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(wearable->getItemID());
if(item)
{
perm_mask = item->getPermissions().getMaskOwner();
is_complete = item->isComplete();
if(!is_complete)
{
item->fetchFromServer();
}
}
}
setUIPermissions(perm_mask, is_complete);
bool editable = updatePermissions();
if (mType == LLWearableType::WT_ALPHA)
{
initPreviousAlphaTextures();
@@ -980,7 +966,7 @@ void LLPanelEditWearable::setWearableIndex(S32 index)
if(subpart_entry)
{
value_map_t sorted_params;
getSortedParams(sorted_params, subpart_entry->mEditGroup, ((perm_mask & PERM_MODIFY) && is_complete) ? TRUE : FALSE);
getSortedParams(sorted_params, subpart_entry->mEditGroup, editable);
buildParamList(mCustomizeFloater->getScrollingPanelList(), sorted_params);
}
@@ -1144,6 +1130,10 @@ LLViewerWearable* LLPanelEditWearable::getWearable() const
return mCurrentWearable;//gAgentWearables.getWearable(mType, mCurrentIndex); // TODO: MULTI-WEARABLE
}
U32 LLPanelEditWearable::getIndex() const
{
return mCurrentIndex;
}
void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
{
@@ -1163,7 +1153,18 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
if (entry)
{
// Set the new version
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID());
setNewImageID(entry->mTextureIndex, texture_ctrl->getImageAssetID());
}
else
{
llwarns << "could not get texture picker dictionary entry for wearable of type: " << type << llendl;
}
}
}
void LLPanelEditWearable::setNewImageID(ETextureIndex te_index, LLUUID const& uuid)
{
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid);
if( image->getID() == IMG_DEFAULT )
{
image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
@@ -1171,20 +1172,14 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
if (getWearable())
{
U32 index = gAgentWearables.getWearableIndex(getWearable());
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
gAgentAvatarp->setLocalTexture(te_index, image, FALSE, index);
LLVisualParamHint::requestHintUpdates();
gAgentAvatarp->wearableUpdated(type, FALSE);
gAgentAvatarp->wearableUpdated(mType, FALSE);
}
if (mType == LLWearableType::WT_ALPHA && image->getID() != IMG_INVISIBLE)
{
mPreviousAlphaTexture[entry->mTextureIndex] = image->getID();
mPreviousAlphaTexture[te_index] = image->getID();
}
}
else
{
llwarns << "could not get texture picker dictionary entry for wearable of type: " << type << llendl;
}
}
}
void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* base_ctrl )
@@ -1386,39 +1381,11 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
}
// Update the thumbnails we display
LLViewerWearable* wearable = getWearable();
LLViewerInventoryItem* item = wearable ? gInventory.getItem(wearable->getItemID()) : NULL;
U32 perm_mask = 0x0;
BOOL is_complete = FALSE;
bool can_export = false;
bool can_import = false;
if(item)
{
perm_mask = item->getPermissions().getMaskOwner();
is_complete = item->isComplete();
if (subpart_e < SUBPART_EYES) // body parts only
{
can_import = true;
if (is_complete &&
gAgent.getID() == item->getPermissions().getOwner() &&
gAgent.getID() == item->getPermissions().getCreator() &&
(PERM_ITEM_UNRESTRICTED &
perm_mask) == PERM_ITEM_UNRESTRICTED)
{
can_export = true;
}
}
}
setUIPermissions(perm_mask, is_complete);
bool editable = updatePermissions();
value_map_t sorted_params;
getSortedParams(sorted_params, subpart_entry->mEditGroup, ((perm_mask & PERM_MODIFY) && is_complete) ? TRUE : FALSE);
getSortedParams(sorted_params, subpart_entry->mEditGroup, editable);
buildParamList(mCustomizeFloater->getScrollingPanelList(), sorted_params);
updateScrollingPanelUI();
mCustomizeFloater->childSetEnabled("Export", can_export);
mCustomizeFloater->childSetEnabled("Import", can_import);
// Update the camera
if(gMorphView)
@@ -1434,6 +1401,43 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
}
}
//Singu note: this function was split off from LLPanelEditWearable::changeCamera
// Return true if the current wearable is editable and update state accordingly.
bool LLPanelEditWearable::updatePermissions()
{
LLViewerWearable* wearable = getWearable();
LLViewerInventoryItem* item = wearable ? gInventory.getItem(wearable->getItemID()) : NULL;
U32 perm_mask = wearable ? PERM_NONE : PERM_ALL;
BOOL is_complete = wearable ? FALSE : TRUE;
bool can_export = false;
bool can_import = false;
if (item)
{
perm_mask = item->getPermissions().getMaskOwner();
is_complete = item->isComplete();
//Singu note: allow to import values over any modifiable wearable (why not?).
{
can_import = true;
// Exporting (of slider values) is allowed when the wearable is full perm, and owned by and created by the user.
// Of course, only modifiable is enough for the user to write down the values and enter them else where... but why make it easy for them to break the ToS.
if (is_complete &&
gAgent.getID() == item->getPermissions().getOwner() &&
gAgent.getID() == item->getPermissions().getCreator() &&
(PERM_ITEM_UNRESTRICTED &
perm_mask) == PERM_ITEM_UNRESTRICTED)
{
can_export = true;
}
}
}
setUIPermissions(perm_mask, is_complete);
mCustomizeFloater->childSetEnabled("Export", can_export);
mCustomizeFloater->childSetEnabled("Import", can_import);
return (perm_mask & PERM_MODIFY) && is_complete;
}
void LLPanelEditWearable::updateScrollingPanelList()
{
updateScrollingPanelUI();

View File

@@ -62,10 +62,12 @@ public:
// changes camera angle to default for selected subpart
void changeCamera(U8 subpart);
bool updatePermissions();
const std::string& getLabel() { return LLWearableType::getTypeLabel( mType ); }
LLWearableType::EType getType() const{ return mType; }
LLViewerWearable* getWearable() const;
U32 getIndex() const;
void onTabChanged(LLUICtrl* ctrl);
bool onTabPrecommit();
@@ -108,6 +110,7 @@ public:
void onColorSwatchCommit(const LLUICtrl*);
void onTexturePickerCommit(const LLUICtrl*);
void setNewImageID(ETextureIndex te_index, LLUUID const& uuid); //Singu note: this used to be part of onTexturePickerCommit.
//alpha mask checkboxes
void configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name);

View File

@@ -86,10 +86,11 @@ LLPanelNearByMedia::LLPanelNearByMedia(bool standalone_panel)
{
mHoverTimer.stop();
mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
gSavedSettings.getBOOL("MediaTentativeAutoPlay");
mParcelAudioAutoStart = gSavedSettings.getBOOL("MediaTentativeAutoPlay");
/*gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
gSavedSettings.getBOOL("MediaTentativeAutoPlay");*/
gSavedSettings.getControl(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
//gSavedSettings.getControl(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll", boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll", boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
@@ -911,7 +912,7 @@ void LLPanelNearByMedia::onClickParcelAudioPlay()
}
else
{
gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
LLViewerParcelMedia::playStreamingMusic(LLViewerParcelMgr::getInstance()->getAgentParcel());
}
}
@@ -1265,12 +1266,18 @@ void* createNearbyMediaPanel(void* userdata)
return new LLPanelNearByMedia(false);
}
LLFloaterNearbyMedia::LLFloaterNearbyMedia()
LLFloaterNearbyMedia::LLFloaterNearbyMedia() : mPanel(NULL)
{
mFactoryMap["nearby_media"] = LLCallbackMap(createNearbyMediaPanel, this);
LLUICtrlFactory::getInstance()->buildFloater(this,"floater_nearby_media.xml",&mFactoryMap,false);
}
/*virtual*/ BOOL LLFloaterNearbyMedia::postBuild()
{
mPanel = getChild<LLPanelNearByMedia>("nearby_media",false,false);
return LLFloater::postBuild();
}
// static
void LLFloaterNearbyMedia::updateClass()
{

View File

@@ -189,10 +189,15 @@ public:
static void updateClass();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void onOpen();
virtual void handleReshape(const LLRect& new_rect, bool by_user);
LLPanelNearByMedia* getMediaPanel() { return mPanel; }
private:
LLPanelNearByMedia* mPanel;
};
#endif // LL_LLPANELNEARBYMEDIA_H

View File

@@ -840,6 +840,7 @@ void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to
if (objectp->getNumTEs() > 0)
{
nodep->selectAllTEs(TRUE);
objectp->setAllTESelected(true);
}
else
{
@@ -897,10 +898,12 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
else if (face == SELECT_ALL_TES)
{
nodep->selectAllTEs(TRUE);
objectp->setAllTESelected(true);
}
else if (0 <= face && face < SELECT_MAX_TES)
{
nodep->selectTE(face, TRUE);
objectp->setTESelected(face, true);
}
else
{
@@ -1124,6 +1127,7 @@ LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects()
// flag this object as selected
objectp->setSelected(TRUE);
objectp->setAllTESelected(true);
mSelectedObjects->mSelectType = getSelectTypeForObject(objectp);
@@ -1351,6 +1355,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
if (nodep->isTESelected(te))
{
nodep->selectTE(te, FALSE);
objectp->setTESelected(te, false);
}
else
{

View File

@@ -87,6 +87,7 @@
std::string getProfileURL(const std::string& agent_name);
/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
/*static*/ const char* LLViewerMedia::AUTO_PLAY_PRIM_MEDIA_SETTING = "PrimMediaAutoPlayEnable";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
@@ -1103,7 +1104,7 @@ void LLViewerMedia::setAllMediaEnabled(bool val)
}
else
{
gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
LLViewerParcelMedia::playStreamingMusic(LLViewerParcelMgr::getInstance()->getAgentParcel());
}
}
}
@@ -3857,9 +3858,19 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
//
bool LLViewerMediaImpl::isAutoPlayable() const
{
return (mMediaAutoPlay &&
gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
static const LLCachedControl<bool> media_tentative_auto_play("MediaTentativeAutoPlay",false);
static const LLCachedControl<bool> auto_play_parcel_media(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING,false);
static const LLCachedControl<bool> auto_play_prim_media(LLViewerMedia::AUTO_PLAY_PRIM_MEDIA_SETTING,false);
if(mMediaAutoPlay && media_tentative_auto_play)
{
if(getUsedInUI())
return true;
else if(isParcelMedia() && auto_play_parcel_media)
return true;
else if(auto_play_prim_media)
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -84,6 +84,7 @@ public:
// String to get/set media autoplay in gSavedSettings
static const char* AUTO_PLAY_MEDIA_SETTING;
static const char* AUTO_PLAY_PRIM_MEDIA_SETTING;
static const char* SHOW_MEDIA_ON_OTHERS_SETTING;
static const char* SHOW_MEDIA_WITHIN_PARCEL_SETTING;
static const char* SHOW_MEDIA_OUTSIDE_PARCEL_SETTING;

View File

@@ -414,7 +414,7 @@ void LLViewerMediaFocus::update()
normal = mHoverObjectNormal;
}
if(media_impl && viewer_object)
if(media_impl && viewer_object && !media_impl->isForcedUnloaded())
{
// We have an object and impl to point at.

View File

@@ -4377,7 +4377,7 @@ void handle_dump_archetype_xml(void *)
avatar = gAgentAvatarp;
}
std::string file_name = avatar->getFullname() + (avatar->isSelf() ? "_s" : "_o") + ".xml";
std::string file_name = avatar->getFullname() + (avatar->isSelf() ? "_s" : "_o") + "?000.xml";
std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
AIFilePicker* filepicker = AIFilePicker::create();

View File

@@ -55,6 +55,7 @@
#include "llfloaterbuyland.h"
#include "llfloatergroups.h"
//#include "llfloaterhtml.h"
#include "llpanelnearbymedia.h"
#include "llfloatersellland.h"
#include "llfloaterteleporthistory.h"
#include "llfloatertools.h"
@@ -1799,6 +1800,9 @@ void optionally_start_music(LLParcel* parcel)
{
if (gSavedSettings.getBOOL("AudioStreamingMusic"))
{
// Make the user click the start button on the overlay bar. JC
// llinfos << "Starting parcel music " << parcel->getMusicURL() << llendl;
@@ -1806,8 +1810,19 @@ void optionally_start_music(LLParcel* parcel)
// changed as part of SL-4878
if (gOverlayBar && gOverlayBar->musicPlaying())
{
LLViewerParcelMedia::playStreamingMusic(parcel);
LLPanelNearByMedia* nearby_media_panel = LLFloaterNearbyMedia::instanceExists() ? LLFloaterNearbyMedia::getInstance()->getMediaPanel() : NULL;
if ((nearby_media_panel &&
nearby_media_panel->getParcelAudioAutoStart()) ||
// or they have expressed no opinion in the UI, but have autoplay on...
(!nearby_media_panel &&
/*gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&*/
gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
{
LLViewerParcelMedia::playStreamingMusic(parcel);
return;
}
}
gAudiop->startInternetStream(LLStringUtil::null);
}
}

View File

@@ -1671,6 +1671,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ProductInfoRequest");
capabilityNames.append("ProvisionVoiceAccountRequest");
capabilityNames.append("RemoteParcelRequest");
capabilityNames.append("RenderMaterials");
capabilityNames.append("RequestTextureDownload");
//capabilityNames.append("ResourceCostSelected"); //Object weights (llfloaterobjectweights.cpp)
capabilityNames.append("RetrieveNavMeshSrc");

View File

@@ -7618,34 +7618,33 @@ bool LLVOAvatar::visualParamWeightsAreDefault()
return rtn;
}
void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value)
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value)
{
std::string type_string = "unknown";
if (dynamic_cast<LLTexLayerParamAlpha*>(viewer_param))
if (dynamic_cast<LLTexLayerParamAlpha const*>(viewer_param))
type_string = "param_alpha";
if (dynamic_cast<LLTexLayerParamColor*>(viewer_param))
if (dynamic_cast<LLTexLayerParamColor const*>(viewer_param))
type_string = "param_color";
if (dynamic_cast<LLDriverParam*>(viewer_param))
if (dynamic_cast<LLDriverParam const*>(viewer_param))
type_string = "param_driver";
if (dynamic_cast<LLPolyMorphTarget*>(viewer_param))
if (dynamic_cast<LLPolyMorphTarget const*>(viewer_param))
type_string = "param_morph";
if (dynamic_cast<LLPolySkeletalDistortion*>(viewer_param))
if (dynamic_cast<LLPolySkeletalDistortion const*>(viewer_param))
type_string = "param_skeleton";
S32 wtype = -1;
LLViewerVisualParam *vparam = dynamic_cast<LLViewerVisualParam*>(viewer_param);
LLViewerVisualParam const* vparam = dynamic_cast<LLViewerVisualParam const*>(viewer_param);
if (vparam)
{
wtype = vparam->getWearableType();
}
S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight());
apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\"/>\n",
apr_file_printf(file.getFileHandle(), "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\"/>\n",
viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(),
LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str()
// param_location_name(vparam->getParamLocation()).c_str()
);
}
void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
const std::vector<F32>& params_for_dump,
const LLTEContents& tec)
@@ -7675,7 +7674,7 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
}
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
F32 value = params_for_dump[i];
dump_visual_param(file, viewer_param, value);
dump_visual_param(outfile, viewer_param, value);
param = getNextVisualParam();
}
for (U32 i = 0; i < tec.face_count; i++)
@@ -8301,7 +8300,24 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
dumpArchetypeXML_cont(fullpath, group_by_wearables);
}
void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables )
//static
void LLVOAvatar::dumpArchetypeXML_header(LLAPRFile& file)
{
apr_file_t* fp = file.getFileHandle();
apr_file_printf(fp, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n");
apr_file_printf(fp, "<linden_genepool version=\"1.0\">\n");
apr_file_printf(fp, "\n\t<archetype name=\"???\">\n");
}
//static
void LLVOAvatar::dumpArchetypeXML_footer(LLAPRFile& file)
{
apr_file_t* fp = file.getFileHandle();
apr_file_printf(fp, "\t</archetype>\n");
apr_file_printf(fp, "\n</linden_genepool>\n");
}
void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables)
{
LLAPRFile outfile;
outfile.open(fullpath, LL_APR_WB );
@@ -8315,9 +8331,7 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
llinfos << "xmlfile write handle obtained : " << fullpath << llendl;
}
apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" );
apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" );
apr_file_printf( file, "\n\t<archetype name=\"???\">\n" );
LLVOAvatar::dumpArchetypeXML_header(outfile);
if (group_by_wearables)
{
@@ -8332,7 +8346,7 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
if( (viewer_param->getWearableType() == type) &&
(viewer_param->isTweakable() ) )
{
dump_visual_param(file, viewer_param, viewer_param->getWeight());
dump_visual_param(outfile, viewer_param, viewer_param->getWeight());
}
}
@@ -8358,7 +8372,7 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
dump_visual_param(file, viewer_param, viewer_param->getWeight());
dump_visual_param(outfile, viewer_param, viewer_param->getWeight());
}
for (U8 te = 0; te < TEX_NUM_INDICES; te++)
@@ -8376,8 +8390,8 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
}
}
apr_file_printf( file, "\t</archetype>\n" );
apr_file_printf( file, "\n</linden_genepool>\n" );
LLVOAvatar::dumpArchetypeXML_footer(outfile);
bool ultra_verbose = false;
if (isSelf() && ultra_verbose)
@@ -8388,7 +8402,6 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
// File will close when handle goes out of scope
}
void LLVOAvatar::setVisibilityRank(U32 rank)
{
if (mDrawable.isNull() || mDrawable->isDead())

View File

@@ -66,6 +66,7 @@ extern const LLUUID ANIM_AGENT_PELVIS_FIX;
extern const LLUUID ANIM_AGENT_TARGET;
extern const LLUUID ANIM_AGENT_WALK_ADJUST;
class LLAPRFile;
class LLViewerWearable;
class LLVoiceVisualizer;
class LLHUDNameTag;
@@ -986,6 +987,8 @@ private:
// General
//--------------------------------------------------------------------
public:
static void dumpArchetypeXML_header(LLAPRFile& file);
static void dumpArchetypeXML_footer(LLAPRFile& file);
void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false);
void dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables);
void dumpAppearanceMsgParams( const std::string& dump_prefix,

View File

@@ -3195,7 +3195,7 @@ void LLVOAvatarSelf::dumpScratchTextureByteCount()
llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl;
}
void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value);
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
{
@@ -3223,7 +3223,7 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
it != v_params.end(); ++it)
{
LLVisualParam *param = *it;
dump_visual_param(file, param, param->getWeight());
dump_visual_param(outfile, param, param->getWeight());
}
}
}

View File

@@ -41,6 +41,7 @@
#include "lldir.h"
#include "llflexibleobject.h"
#include "llfloatertools.h"
#include "llmaterialid.h"
#include "llmaterialtable.h"
#include "llprimitive.h"
#include "llvolume.h"
@@ -81,6 +82,7 @@
#include "llviewershadermgr.h"
#include "llvoavatar.h"
#include "llvocache.h"
#include "llmaterialmgr.h"
// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d)
#include "rlvhandler.h"
@@ -1942,6 +1944,62 @@ S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
return res;
}
void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te)
{
LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID);
if (pVol)
{
LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL;
if (te >= pVol->getNumTEs())
return;
LLTextureEntry* texture_entry = pVol->getTE(te);
if (texture_entry && (texture_entry->getMaterialID() == pMaterialID))
{
pVol->setTEMaterialParams(te, pMaterialParams);
}
}
}
S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
{
S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID);
LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
<< LL_ENDL;
LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL;
if (res)
{
LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3));
setChanged(ALL_CHANGED);
if (!mDrawable.isNull())
{
gPipeline.markTextured(mDrawable);
gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL);
}
mFaceMappingChanged = TRUE;
}
return res;
}
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
{
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
<< LL_ENDL;
setChanged(ALL_CHANGED);
if (!mDrawable.isNull())
{
gPipeline.markTextured(mDrawable);
gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL);
}
mFaceMappingChanged = TRUE;
return TEM_CHANGE_TEXTURE;
}
S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
{
S32 res = LLViewerObject::setTEScale(te, s, t);
@@ -3988,7 +4046,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
(type == LLRenderPass::PASS_INVISIBLE) ||
(type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT));
(type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) ||
(type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) ||
(facep->getTextureEntry()->getFullbright());
if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL))
{
@@ -4026,6 +4086,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LLViewerTexture* tex = facep->getTexture();
U8 index = facep->getTextureIndex();
LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID();
bool batchable = false;
@@ -4371,66 +4433,104 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLViewerTexture* tex = facep->getTexture();
U32 type = gPipeline.getPoolTypeFromTE(te, tex);
if (type == LLDrawPool::POOL_ALPHA)
{
if (te->getColor().mV[3] > 0.f)
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
}
}
}
else if (te->getShiny())
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY);
}
else
{
if (LLPipeline::sRenderDeferred)
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY);
}
}
}
else
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
}
}
if (te->getGlow())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);
}
if (LLPipeline::sRenderDeferred)
LLMaterial* mat = te->getMaterialParams().get();
if (mat)
{
if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())
bool fullbright = te->getFullbright();
bool is_alpha = type == LLDrawPool::POOL_ALPHA;
U8 mode = mat->getDiffuseAlphaMode();
bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f)
{
if (te->getBumpmap())
pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
}
else if (is_alpha || (te->getColor().mV[3] < 0.999f))
{
if (te->getColor().mV[3] > 0.f)
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP);
pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA);
}
}
else if (gPipeline.canUseVertexShaders()
&& LLPipeline::sRenderBump
&& te->getShiny()
&& can_be_shiny)
{
pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY);
}
else
{
pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
}
}
else
{
if (type == LLDrawPool::POOL_ALPHA)
{
if (te->getColor().mV[3] > 0.f)
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
}
}
}
else if (te->getShiny())
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE);
if (LLPipeline::sRenderDeferred)
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY);
}
}
}
else
{
if (te->getFullbright())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
}
}
if (LLPipeline::sRenderDeferred)
{
if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())
{
if (te->getBumpmap())
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP);
}
else
{
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE);
}
}
}
}
@@ -5058,7 +5158,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
index_offset += facep->getGeomCount();
indices_index += facep->getIndicesCount();
//append face to appropriate render batch
BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA;
@@ -5078,7 +5177,46 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
if (is_alpha)
LLMaterial* mat = te->getMaterialParams().get();
bool can_be_shiny = true;
if (mat)
{
U8 mode = mat->getDiffuseAlphaMode();
can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
}
bool use_legacy_bump = te->getBumpmap();
if (mat)
{
U8 mode = mat->getDiffuseAlphaMode();
if (te->getColor().mV[3] < 0.999f)
{
mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
}
if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK);
}
else if (is_alpha || (te->getColor().mV[3] < 0.999f))
{
registerFace(group, facep, LLRenderPass::PASS_ALPHA);
}
else if (gPipeline.canUseVertexShaders()
&& LLPipeline::sRenderBump
&& te->getShiny()
&& can_be_shiny)
{
registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY);
}
else
{
registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE);
}
}
else if (is_alpha)
{
// can we safely treat this as an alpha mask?
if (facep->getFaceColor().mV[3] <= 0.f)
@@ -5103,7 +5241,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else if (gPipeline.canUseVertexShaders()
&& LLPipeline::sRenderBump
&& te->getShiny())
&& te->getShiny()
&& can_be_shiny)
{ //shiny
if (tex->getPrimaryFormat() == GL_ALPHA)
{ //invisiprim+shiny
@@ -5120,7 +5259,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);
}
}
else if (te->getBumpmap())
else if (use_legacy_bump)
{ //register in deferred bump pass
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
@@ -5147,25 +5286,40 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else if (fullbright || bake_sunlight)
{ //fullbright
registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap())
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK);
}
else
{
registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
}
if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump)
{ //if this is the deferred render and a bump map is present, register in post deferred bump
registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);
}
}
else
{
if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap())
if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump)
{ //non-shiny or fullbright deferred bump
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
else
{ //all around simple
llassert(mask & LLVertexBuffer::MAP_NORMAL);
registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{ //material alpha mask can be respected in non-deferred
registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK);
}
else
{
registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
}
}
}
if (!gPipeline.canUseVertexShaders() &&
!is_alpha &&
te->getShiny() &&
@@ -5181,7 +5335,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright);
facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE);
if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump)
if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump)
{
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}

View File

@@ -44,6 +44,7 @@
class LLViewerTextureAnim;
class LLDrawPool;
class LLMaterialID;
class LLSelectNode;
class LLObjectMediaDataClient;
class LLObjectMediaNavigateClient;
@@ -191,6 +192,11 @@ public:
/*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump);
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags);
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te);
/*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
/*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
/*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
/*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);

View File

@@ -293,6 +293,7 @@ void LLWorld::removeRegion(const LLHost &host)
mCulledRegionList.remove(regionp);
mVisibleRegionList.remove(regionp);
mRegionRemovedSignal(regionp);
//double check all objects of this region are removed.
gObjectList.clearAllMapObjectsInRegion(regionp) ;
//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
@@ -420,6 +421,19 @@ LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle)
return NULL;
}
LLViewerRegion* LLWorld::getRegionFromID(const LLUUID& region_id)
{
for (region_list_t::iterator iter = mRegionList.begin();
iter != mRegionList.end(); ++iter)
{
LLViewerRegion* regionp = *iter;
if (regionp->getRegionID() == region_id)
{
return regionp;
}
}
return NULL;
}
void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
{
@@ -1506,6 +1520,11 @@ bool LLWorld::isRegionListed(const LLViewerRegion* region) const
return it != mRegionList.end();
}
boost::signals2::connection LLWorld::setRegionRemovedCallback(const region_remove_signal_t::slot_type& cb)
{
return mRegionRemovedSignal.connect(cb);
}
LLHTTPRegistration<LLEstablishAgentCommunication>
gHTTPRegistrationEstablishAgentCommunication(
"/message/EstablishAgentCommunication");

View File

@@ -82,6 +82,7 @@ public:
LLViewerRegion* getRegionFromPosGlobal(const LLVector3d &pos);
LLViewerRegion* getRegionFromPosAgent(const LLVector3 &pos);
LLViewerRegion* getRegionFromHandle(const U64 &handle);
LLViewerRegion* getRegionFromID(const LLUUID& region_id);
BOOL positionRegionValidGlobal(const LLVector3d& pos); // true if position is in valid region
LLVector3d clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos);
@@ -157,6 +158,8 @@ public:
typedef std::list<LLViewerRegion*> region_list_t;
const region_list_t& getRegionList() const { return mActiveRegionList; }
typedef boost::signals2::signal<void(LLViewerRegion*)> region_remove_signal_t;
boost::signals2::connection setRegionRemovedCallback(const region_remove_signal_t::slot_type& cb);
// Returns lists of avatar IDs and their world-space positions within a given distance of a point.
// All arguments are optional. Given containers will be emptied and then filled.
// Not supplying origin or radius input returns data on all avatars in the known regions.
@@ -176,6 +179,8 @@ private:
region_list_t mVisibleRegionList;
region_list_t mCulledRegionList;
region_remove_signal_t mRegionRemovedSignal;
// Number of points on edge
static const U32 mWidth;

View File

@@ -1435,10 +1435,12 @@ one from scratch and wear it.
</text>
<button name="Import" label="Import"
bottom="-486" left="10" height="20" width="70"
follows="left|bottom" font="SansSerif" halign="center" />
follows="left|bottom" font="SansSerif" halign="center"
tool_tip="Import to currently selected wearable; current wearable must be modifiable" />
<button name="Export" label="Export"
bottom="-506" left="10" height="20" width="70"
follows="left|bottom" font="SansSerif" halign="center" />
follows="left|bottom" font="SansSerif" halign="center"
tool_tip="Export currently selected wearable; asset must be copy/mod/trans and you need to be the creator" />
<button bottom="-536" follows="right|bottom" font="SansSerif" halign="center"
height="20" label="Cancel" label_selected="Cancel" mouse_opaque="true"
name="Cancel" right="-10" scale_image="true" width="100" />

View File

@@ -107,6 +107,9 @@
<menu_item_call enabled="true" label="Copy UUID" mouse_opaque="true" name="CopyUUID">
<on_click function="Avatar.CopyUUID" />
</menu_item_call>
<menu_item_call label="Save OBJ..." mouse_opaque="true" name="Save OBJ...">
<on_click function="Avatar.SaveAsOBJ" />
</menu_item_call>
</pie_menu>
<menu_item_call enabled="true" label="Stand Up" name="Stand Up Self">
<on_click function="Self.SitOrStand"/>
@@ -119,7 +122,4 @@
<on_click function="ShowFloater" userdata="appearance" />
<on_enable function="Edit.EnableCustomizeAvatar" />
</menu_item_call>
<menu_item_call label="Save OBJ..." mouse_opaque="true" name="Save OBJ...">
<on_click function="Avatar.SaveAsOBJ" />
</menu_item_call>
</pie_menu>

View File

@@ -9638,10 +9638,16 @@ Would you like to enable announcing keys to objects in the sim?
</notification>
<notification
icon="notify.tga"
icon="alertmodal.tga"
name="WavefrontExportPartial"
type="notify">
Unable to include [OBJECT] in export, insufficient permissions.
type="alertmodal">
Unable to include [FAILED] out of [TOTAL] objects in export due to insufficient permissions.
Do you wish to export anyway?
<usetemplate
name="okcancelbuttons"
yestext="Proceed"
notext="Cancel" />
</notification>
<notification

View File

@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel border="true" bottom="-409" height="408" label="Audio &amp; Video" left="102" name="Media panel" width="517">
<text bottom="-22" height="12" left="10" name="muting_text">Volume:</text>
<text bottom="-215" name="streaming_prefs_text">Streaming Preferences:</text>
<text bottom="-300" height="12" name="audio_prefs_text">Audio Preferences:</text>
<panel border="true" bottom="-200" filename="panel_audio.xml" height="165" label="Volume" left="142" name="Volume Panel" width="260"/>
<check_box bottom="-220" control_name="AudioStreamingMusic" height="16" initial_value="true" label="Play Streaming Music When Available (uses more bandwidth)" left="142" name="streaming_music"/>
<text bottom="-190" name="streaming_prefs_text">Streaming Preferences:</text>
<text bottom="-295" height="12" name="audio_prefs_text">Audio Preferences:</text>
<panel border="true" bottom="-172" filename="panel_audio.xml" height="165" label="Volume" left="142" name="Volume Panel" width="260"/>
<check_box bottom="-195" control_name="MediaEnableFilter" follows="top" height="16" initial_value="true" label="Ask for permission (enables filtering)" left="142" name="media_filter_enable"/>
<check_box bottom_delta="-20" control_name="AudioStreamingMusic" follows="top" height="16" initial_value="true" label="Play Streaming Music When Available (uses more bandwidth)" name="streaming_music"/>
<check_box bottom_delta="-20" control_name="AudioStreamingMedia" follows="top" height="16" initial_value="true" label="Play Streaming Media When Available (uses more bandwidth)" name="streaming_video"/>
<check_box bottom_delta="-20" control_name="ParcelMediaAutoPlayEnable" follows="top" height="16" initial_value="true" label="Automatically play media" left="162" name="auto_streaming_video"/>
<check_box bottom_delta="-20" control_name="MediaEnableFilter" follows="top" height="16" initial_value="true" label="Ask for permission (enables filtering)" name="streaming_video"/>
<check_box bottom_delta="-20" control_name="PrimMediaAutoPlayEnable" follows="top" height="16" initial_value="true" label="Automatically play prim media" left="162" name="auto_prim_streaming_video"/>
<check_box bottom_delta="-20" control_name="ParcelMediaAutoPlayEnable" follows="top" height="16" initial_value="true" label="Automatically play parcel media" left="162" name="auto_streaming_video"/>
<check_box bottom_delta="-25" control_name="MuteWhenMinimized" follows="top" height="16" initial_value="true" label="Mute Audio When Window Minimized" left="142" name="mute_when_minimized"/>
<slider bottom_delta="-20" control_name="AudioLevelDoppler" edit_text="true" follows="top" height="15" increment="0.1" initial_val="1" label="Doppler Effect" label_width="130" left="148" max_val="2" min_val="0" name="Doppler Effect" show_text="true" width="300" />
<slider bottom_delta="-20" control_name="AudioLevelRolloff" edit_text="true" follows="top" height="15" increment="0.1" initial_val="1" label="Rolloff Factor (Default)" label_width="130" max_val="2" min_val="0" name="Rolloff Factor" width="300"/>

View File

@@ -39,6 +39,7 @@
#include "llpluginmessageclasses.h"
#include "llsdserialize.h"
#include "aifilepicker.h"
#include "lldir.h"
#if LL_WINDOWS
#include "llviewerwindow.h"
#endif
@@ -195,9 +196,26 @@ void AIFilePicker::open(ELoadFilter filter, std::string const& default_path, std
void AIFilePicker::open(std::string const& filename, ESaveFilter filter, std::string const& default_path, std::string const& context)
{
mFilename = filename;
mFilename = LLDir::getScrubbedFileName(filename);
mContext = context;
mFolder = AIFilePicker::get_folder(default_path, context);
// If the basename of filename ends on "?000", then check if a file with that name exists and if so, increment the number.
std::string basename = gDirUtilp->getBaseFileName(filename, true);
size_t len = basename.size();
if (len >= 4 && basename.substr(len - 4) == "?000")
{
basename = LLDir::getScrubbedFileName(basename.substr(0, len - 4));
std::string extension = gDirUtilp->getExtension(mFilename);
for (int n = 0;; ++n)
{
mFilename = llformat("%s_%03u.%s", basename.c_str(), n, extension.c_str());
std::string fullpath = mFolder + gDirUtilp->getDirDelimiter() + mFilename;
if (n == 999 || !gDirUtilp->fileExists(fullpath))
{
break;
}
}
}
mOpenType = save;
switch(filter)
{