From 940adfe4d02ab0ecf69635afe7f959abe1fe2c44 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 8 May 2015 11:16:51 -0400 Subject: WIP bvh diagnostics --- indra/llcharacter/llbvhloader.cpp | 124 +++++++++++++++++++----------- indra/llcharacter/llbvhloader.h | 4 + indra/llcharacter/llkeyframemotion.cpp | 7 ++ indra/newview/app_settings/logcontrol.xml | 1 + indra/newview/llfloaterbvhpreview.cpp | 8 ++ 5 files changed, 99 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 0d558aeaa2..754b9362cd 100755 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -42,10 +42,12 @@ using namespace std; #define INCHES_TO_METERS 0.02540005f -const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.03f * 0.03f; +//const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.03f * 0.03f; +const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.0f; const F32 ROTATION_KEYFRAME_THRESHOLD = 0.01f; -const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.001f * 0.001f; +//const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.001f * 0.001f; +const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.0f; const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ @@ -166,7 +168,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error LL_INFOS()<<"Load Status 00 : "<< loadStatus << LL_ENDL; if (mStatus == E_ST_NO_XLT_FILE) { - //LL_WARNS() << "NOTE: No translation table found." << LL_ENDL; + LL_WARNS() << "NOTE: No translation table found." << LL_ENDL; loadStatus = mStatus; return; } @@ -174,7 +176,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error { if (mStatus != E_ST_OK) { - //LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; + LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; errorLine = getLineNumber(); loadStatus = mStatus; return; @@ -184,10 +186,13 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error char error_text[128]; /* Flawfinder: ignore */ S32 error_line; mStatus = loadBVHFile(buffer, error_text, error_line); + + LL_INFOS("BVH") << "Raw data from file" << LL_ENDL; + dumpBVHInfo(); if (mStatus != E_ST_OK) { - //LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; + LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; loadStatus = mStatus; errorLine = getLineNumber(); return; @@ -196,6 +201,9 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error applyTranslations(); optimize(); + LL_INFOS("BVH") << "Ater optimize" << LL_ENDL; + dumpBVHInfo(); + mInitialized = TRUE; } @@ -666,6 +674,33 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) return E_ST_OK; } +void LLBVHLoader::dumpBVHInfo() +{ + for (U32 j=0; jmName << LL_ENDL; + for (S32 i=0; imKeys[llmax(i-1,0)]; + Key &key = joint->mKeys[i]; + if ((i==0) || + (key.mPos[0] != prevkey.mPos[0]) || + (key.mPos[1] != prevkey.mPos[1]) || + (key.mPos[2] != prevkey.mPos[2]) || + (key.mRot[0] != prevkey.mRot[0]) || + (key.mRot[1] != prevkey.mRot[1]) || + (key.mRot[2] != prevkey.mRot[2]) + ) + { + LL_INFOS() << "FRAME " << i + << " POS " << key.mPos[0] << "," << key.mPos[1] << "," << key.mPos[2] + << " ROT " << key.mRot[0] << "," << key.mRot[1] << "," << key.mRot[2] << LL_ENDL; + } + } + } + +} //------------------------------------------------------------------------ // LLBVHLoader::loadBVHFile() @@ -746,6 +781,7 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & { iter++; // { iter++; // OFFSET + iter++; // } S32 depth = 0; for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--) { @@ -790,11 +826,14 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & //---------------------------------------------------------------- mJoints.push_back( new Joint( jointName ) ); Joint *joint = mJoints.back(); + LL_INFOS() << "Created joint " << jointName << LL_ENDL; + LL_INFOS() << "- index " << mJoints.size()-1 << LL_ENDL; S32 depth = 1; for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--) { Joint *pjoint = mJoints[parent_joints[j]]; + LL_INFOS() << "- ancestor " << pjoint->mName << LL_ENDL; if (depth > pjoint->mChildTreeMaxDepth) { pjoint->mChildTreeMaxDepth = depth; @@ -862,6 +901,19 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ return E_ST_NO_CHANNELS; } + int res = sscanf(line.c_str(), " CHANNELS %d", &joint->mNumChannels); + if ( res != 1 ) + { + // Assume default if not otherwise specified. + if (mJoints.size()==1) + { + joint->mNumChannels = 6; + } + else + { + joint->mNumChannels = 3; + } + } //---------------------------------------------------------------- // get rotation order @@ -961,57 +1013,39 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & line = (*(iter++)); err_line++; - // read and store values - const char *p = line.c_str(); + // Split line into a collection of floats. + std::deque floats; + boost::char_separator whitespace_sep("\t "); + tokenizer float_tokens(line, whitespace_sep); + tokenizer::iterator float_token_iter = float_tokens.begin(); + while (float_token_iter != float_tokens.end()) + { + floats.push_back(std::stof(*(float_token_iter++))); + } + LL_INFOS() << "Got " << floats.size() << " floats " << LL_ENDL; for (U32 j=0; jmKeys.push_back( Key() ); Key &key = joint->mKeys.back(); - // get 3 pos values for root joint only - if (j==0) - { - if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 ) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_POS; - } - } - - // skip to next 3 values in the line - p = find_next_whitespace(p); - if (!p) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; - } - p = find_next_whitespace(++p); - if (!p) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; - } - p = find_next_whitespace(++p); - if (!p) + if (floats.size() < joint->mNumChannels) { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; + strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ + return E_ST_NO_POS; } - // get 3 rot values for joint - F32 rot[3]; - if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 ) + // assume either numChannels == 6, in which case we have pos + rot, + // or numChannels == 3, in which case we have only rot. + if (joint->mNumChannels == 6) { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; + key.mPos[0] = floats.front(); floats.pop_front(); + key.mPos[1] = floats.front(); floats.pop_front(); + key.mPos[2] = floats.front(); floats.pop_front(); } - - p++; - - key.mRot[ joint->mOrder[0]-'X' ] = rot[0]; - key.mRot[ joint->mOrder[1]-'X' ] = rot[1]; - key.mRot[ joint->mOrder[2]-'X' ] = rot[2]; + key.mRot[ joint->mOrder[0]-'X' ] = floats.front(); floats.pop_front(); + key.mRot[ joint->mOrder[1]-'X' ] = floats.front(); floats.pop_front(); + key.mRot[ joint->mOrder[2]-'X' ] = floats.front(); floats.pop_front(); } } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index f816b76277..033d8714a9 100755 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -102,6 +102,7 @@ struct Joint mNumRotKeys = 0; mChildTreeMaxDepth = 0; mPriority = 0; + mNumChannels = 3; } // Include aligned members first @@ -123,6 +124,7 @@ struct Joint S32 mNumRotKeys; S32 mChildTreeMaxDepth; S32 mPriority; + S32 mNumChannels; }; @@ -272,6 +274,8 @@ public: // Returns status code. ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line); + void dumpBVHInfo(); + // Applies translations to BVH data loaded. void applyTranslations(); diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index cd201a65b4..8b463a2b8c 100755 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1881,6 +1881,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU32(mJointMotionList->mHandPose, "hand_pose"); success &= dp.packU32(mJointMotionList->getNumJointMotions(), "num_joints"); + LL_DEBUGS("BVH") << "bvh" << LL_ENDL; + for (U32 i = 0; i < mJointMotionList->getNumJointMotions(); i++) { JointMotion* joint_motionp = mJointMotionList->getJointMotion(i); @@ -1888,6 +1890,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packS32(joint_motionp->mPriority, "joint_priority"); success &= dp.packS32(joint_motionp->mRotationCurve.mNumKeys, "num_rot_keys"); + LL_DEBUGS("BVH") << "Joint " << joint_motionp->mJointName << LL_ENDL; for (RotationCurve::key_map_t::iterator iter = joint_motionp->mRotationCurve.mKeys.begin(); iter != joint_motionp->mRotationCurve.mKeys.end(); ++iter) { @@ -1905,6 +1908,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(x, "rot_angle_x"); success &= dp.packU16(y, "rot_angle_y"); success &= dp.packU16(z, "rot_angle_z"); + + LL_DEBUGS("BVH") << " rot " << rot_key.mTime << " - " <mPositionCurve.mNumKeys, "num_pos_keys"); @@ -1923,6 +1928,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(x, "pos_x"); success &= dp.packU16(y, "pos_y"); success &= dp.packU16(z, "pos_z"); + + LL_DEBUGS("BVH") << " pos " << pos_key.mTime << pos_key.mPosition.mV[VX] <<","<< pos_key.mPosition.mV[VY] <<","<< pos_key.mPosition.mV[VZ] << LL_ENDL; } } diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index de3732f339..6d5cf6e8f7 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,6 +42,7 @@ tags + BVH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/avatar_skeleton_orig.xml b/indra/newview/character/avatar_skeleton_orig.xml new file mode 100644 index 0000000000..6b07bbc1d3 --- /dev/null +++ b/indra/newview/character/avatar_skeleton_orig.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 2a2c0b81f0..23c5b7192d 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1316,48 +1316,8 @@ LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* pre , mJointsFromNode( jointsFromNodes ) , LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0) { - mJointMap["mPelvis"] = "mPelvis"; - mJointMap["mTorso"] = "mTorso"; - mJointMap["mChest"] = "mChest"; - mJointMap["mNeck"] = "mNeck"; - mJointMap["mHead"] = "mHead"; - mJointMap["mSkull"] = "mSkull"; - mJointMap["mEyeRight"] = "mEyeRight"; - mJointMap["mEyeLeft"] = "mEyeLeft"; - mJointMap["mCollarLeft"] = "mCollarLeft"; - mJointMap["mShoulderLeft"] = "mShoulderLeft"; - mJointMap["mElbowLeft"] = "mElbowLeft"; - mJointMap["mWristLeft"] = "mWristLeft"; - mJointMap["mCollarRight"] = "mCollarRight"; - mJointMap["mShoulderRight"] = "mShoulderRight"; - mJointMap["mElbowRight"] = "mElbowRight"; - mJointMap["mWristRight"] = "mWristRight"; - mJointMap["mHipRight"] = "mHipRight"; - mJointMap["mKneeRight"] = "mKneeRight"; - mJointMap["mAnkleRight"] = "mAnkleRight"; - mJointMap["mFootRight"] = "mFootRight"; - mJointMap["mToeRight"] = "mToeRight"; - mJointMap["mHipLeft"] = "mHipLeft"; - mJointMap["mKneeLeft"] = "mKneeLeft"; - mJointMap["mAnkleLeft"] = "mAnkleLeft"; - mJointMap["mFootLeft"] = "mFootLeft"; - mJointMap["mToeLeft"] = "mToeLeft"; - - // FIXME BENTO change this to use the skeleton info rather than hardwiring - mJointMap["mLeftWingShoulder"] = "mLeftWingShoulder"; - mJointMap["mLeftWingElbow"] = "mLeftWingElbow"; - mJointMap["mLeftWingWrist"] = "mLeftWingWrist"; - mJointMap["mLeftWingTip"] = "mLeftWingTip"; - mJointMap["mRightWingShoulder"] = "mRightWingShoulder"; - mJointMap["mRightWingElbow"] = "mRightWingElbow"; - mJointMap["mRightWingWrist"] = "mRightWingWrist"; - mJointMap["mRightWingTip"] = "mRightWingTip"; - - mJointMap["mTail_1"] = "mTail_1"; - mJointMap["mTail_2"] = "mTail_2"; - mJointMap["mTail_3"] = "mTail_3"; - mJointMap["mTail_4"] = "mTail_4"; - + // Accepted joint aliases - the origins and continued relevance of these is unclear. + mJointMap["avatar_mPelvis"] = "mPelvis"; mJointMap["avatar_mTorso"] = "mTorso"; mJointMap["avatar_mChest"] = "mChest"; @@ -1407,6 +1367,21 @@ LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* pre mJointMap["lShin"] = "mKneeLeft"; mJointMap["lFoot"] = "mFootLeft"; + // Get all standard skeleton joints from the preview avatar. + if (mPreview) + { + LLVOAvatar *av = mPreview->getPreviewAvatar(); + const LLVOAvatar::avatar_joint_list_t &skel = av->getSkeleton(); + for (S32 i=0; igetName()] = joint->getName(); + } + } + } + if (mPreview) { //only try to load from slm if viewer is configured to do so and this is the diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6622fa7d9c..e372676a4f 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1259,7 +1259,7 @@ bool idle_startup() LLPostProcess::initClass(); display_startup(); - LLAvatarAppearance::initClass(); + LLAvatarAppearance::initClass(gSavedSettings.getString("AvatarFileName"),gSavedSettings.getString("SkeletonFileName")); display_startup(); LLViewerObject::initVOClasses(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 253271322c..202b63dec0 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5153,7 +5153,10 @@ void LLVOAvatar::clearAttachmentPosOverrides() for (; iter != end; ++iter) { LLJoint* pJoint = (*iter); - pJoint->clearAttachmentPosOverrides(); + if (pJoint) + { + pJoint->clearAttachmentPosOverrides(); + } } } -- cgit v1.2.3 From 217fb294340b63ce8b3ffa1503649396043c1881 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 19 Aug 2015 16:23:01 -0400 Subject: SL-135 WIP - added additional lad/skel configs --- indra/llcharacter/lljoint.h | 2 +- indra/newview/character/avatar_lad_tentacles.xml | 12505 ++++++++++++++++++ indra/newview/character/avatar_lad_wings_tail.xml | 12615 +++++++++++++++++++ .../character/avatar_skeleton_tentacles.xml | 281 + .../character/avatar_skeleton_wings_tail.xml | 105 + 5 files changed, 25507 insertions(+), 1 deletion(-) create mode 100644 indra/newview/character/avatar_lad_tentacles.xml create mode 100644 indra/newview/character/avatar_lad_wings_tail.xml create mode 100644 indra/newview/character/avatar_skeleton_tentacles.xml create mode 100644 indra/newview/character/avatar_skeleton_wings_tail.xml (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 523cb0b5e6..28109f682a 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,7 +40,7 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; -const U32 LL_CHARACTER_MAX_JOINTS = 48; // must be divisible by 4! +const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() const U32 LL_HAND_JOINT_NUM = (LL_CHARACTER_MAX_JOINTS-1); diff --git a/indra/newview/character/avatar_lad_tentacles.xml b/indra/newview/character/avatar_lad_tentacles.xml new file mode 100644 index 0000000000..9ec6428ee6 --- /dev/null +++ b/indra/newview/character/avatar_lad_tentacles.xml @@ -0,0 +1,12505 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/avatar_lad_wings_tail.xml b/indra/newview/character/avatar_lad_wings_tail.xml new file mode 100644 index 0000000000..ac0b8b5704 --- /dev/null +++ b/indra/newview/character/avatar_lad_wings_tail.xml @@ -0,0 +1,12615 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/avatar_skeleton_tentacles.xml b/indra/newview/character/avatar_skeleton_tentacles.xml new file mode 100644 index 0000000000..c232169b70 --- /dev/null +++ b/indra/newview/character/avatar_skeleton_tentacles.xml @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/character/avatar_skeleton_wings_tail.xml b/indra/newview/character/avatar_skeleton_wings_tail.xml new file mode 100644 index 0000000000..7a088484d8 --- /dev/null +++ b/indra/newview/character/avatar_skeleton_wings_tail.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From fbe58c1bdf565c95e01d67a98faa6f3d00b4df0c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 20 Aug 2015 16:45:02 -0400 Subject: SL-109 WIP - default av is wings+tail, others available with debug settings AvatarFileName and SkeletonFileName --- indra/newview/character/avatar_skeleton_tentacles.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_skeleton_tentacles.xml b/indra/newview/character/avatar_skeleton_tentacles.xml index c232169b70..9863a5cbfd 100644 --- a/indra/newview/character/avatar_skeleton_tentacles.xml +++ b/indra/newview/character/avatar_skeleton_tentacles.xml @@ -1,5 +1,5 @@ - + -- cgit v1.2.3 From 2ea8df0593d520b86bcf958263622218f76ac113 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 26 Aug 2015 10:49:02 -0400 Subject: SL-205 WIP - support for 152-joint rigged meshes with both hardware and software skinning. --- indra/llcharacter/lljoint.h | 1 + indra/llprimitive/llmodel.cpp | 1 + .../app_settings/shaders/class1/avatar/objectSkinV.glsl | 13 ++++++++----- indra/newview/lldrawpoolavatar.cpp | 3 ++- indra/newview/llvovolume.cpp | 1 + 5 files changed, 13 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 28109f682a..d9101c04ca 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,6 +40,7 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; +// BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index ed903146ef..7290fa5f83 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1762,6 +1762,7 @@ LLSD LLModel::writeModel( S32 count = 0; for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter) { + // BENTO JOINT COUNT LIMIT 255? if (iter->mJointIdx < 255 && iter->mJointIdx >= 0) { U8 idx = (U8) iter->mJointIdx; diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 6cd38d8ef5..d3eed775bf 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -24,8 +24,11 @@ ATTRIBUTE vec4 weight4; -uniform mat3 matrixPalette[52]; -uniform vec3 translationPalette[52]; +/* BENTO JOINT COUNT LIMITS + * Note that the value in these two lines also needs to be updated to value-1 several places below. + */ +uniform mat3 matrixPalette[152]; +uniform vec3 translationPalette[152]; mat4 getObjectSkinnedTransform() { @@ -34,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(51.0)); + index = min(index, vec4(151.0)); index = max(index, vec4( 0.0)); float scale = 1.0/(w.x+w.y+w.z+w.w); @@ -68,8 +71,8 @@ mat4 getObjectSkinnedTransform() // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. mat3 dummy1 = matrixPalette[0]; vec3 dummy2 = translationPalette[0]; - mat3 dummy3 = matrixPalette[51]; - vec3 dummy4 = translationPalette[51]; + mat3 dummy3 = matrixPalette[151]; + vec3 dummy4 = translationPalette[151]; #endif } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index f828b56f7f..6c9107cb76 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -55,7 +55,8 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; -#define JOINT_COUNT 52 +// BENTO JOINT COUNT LIMIT +#define JOINT_COUNT 152 LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 267061b83d..7bbaf981ae 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4163,6 +4163,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } //build matrix palette + // BENTO JOINT COUNT LIMIT static const size_t kMaxJoints = 64; LLMatrix4a mp[kMaxJoints]; -- cgit v1.2.3 From 5cacd71c07cd4202784ebf2f826239b4529787ba Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 2 Sep 2015 15:42:22 -0400 Subject: SL-205 WIP - bumped up max joint count in software-skinning pass. --- indra/newview/llvovolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f70280d8c1..25e61c259f 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4164,7 +4164,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons //build matrix palette // BENTO JOINT COUNT LIMIT - static const size_t kMaxJoints = 64; + static const size_t kMaxJoints = 152; LLMatrix4a mp[kMaxJoints]; LLMatrix4* mat = (LLMatrix4*) mp; -- cgit v1.2.3 From 9d44aaab46eff6d16ff50d8b6c12df821f637761 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 8 Sep 2015 12:56:44 -0400 Subject: SL-216 WIP, SL-220 WIP - stray triangles in hw skinning path --- indra/newview/lldrawpoolavatar.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 6c9107cb76..9dd4c2ce0d 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1639,7 +1639,21 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* scale += wght[k]; } - wght *= 1.f/scale; + if (scale > 0.f) + { + wght *= 1.f/scale; + } + else + { + // Complete weighting fail - all zeroes. Just + // pick some values that add up to 1.0 so we + // don't wind up with garbage vertices + // pointing off at (0,0,0) + wght[0] = 1.f; + wght[1] = 0.f; + wght[2] = 0.f; + wght[3] = 0.f; + } for (U32 k = 0; k < 4; k++) { -- cgit v1.2.3 From 2da22ad9fc92b255f9ec63dee11cf56342c2ac33 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 24 Sep 2015 11:35:19 -0400 Subject: SL-227 WIP - initial pass at consolidating skinning code. Less duplication of functionality, still needs more cleanup. --- indra/llcharacter/lljoint.h | 2 + indra/newview/lldrawpoolavatar.cpp | 191 +++++++++++++++++++------------- indra/newview/lldrawpoolavatar.h | 2 + indra/newview/llfloatermodelpreview.cpp | 59 +++------- indra/newview/llvovolume.cpp | 54 +-------- 5 files changed, 139 insertions(+), 169 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index d9101c04ca..b3bf588d79 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,6 +42,8 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 152; + // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() const U32 LL_HAND_JOINT_NUM = (LL_CHARACTER_MAX_JOINTS-1); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index f1bfe4ecb2..7ccc779ba4 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -55,9 +55,6 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; -// BENTO JOINT COUNT LIMIT -#define JOINT_COUNT 152 - LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; @@ -1463,7 +1460,13 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) +void LLDrawPoolAvatar::getRiggedGeometry( + LLFace* face, + LLPointer& buffer, + U32 data_mask, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face) { face->setGeomIndex(0); face->setIndicesIndex(0); @@ -1472,7 +1475,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer face->setTextureIndex(255); if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) - { //make a new buffer + { + // make a new buffer if (sShaderLevel > 0) { buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); @@ -1484,7 +1488,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true); } else - { //resize existing buffer + { + //resize existing buffer buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices); } @@ -1498,9 +1503,9 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer m = m.inverse().transpose(); F32 mat3[] = - { m.m[0], m.m[1], m.m[2], - m.m[4], m.m[5], m.m[6], - m.m[8], m.m[9], m.m[10] }; + { m.m[0], m.m[1], m.m[2], + m.m[4], m.m[5], m.m[6], + m.m[8], m.m[9], m.m[10] }; LLMatrix3 mat_normal(mat3); @@ -1527,14 +1532,98 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer { face->clearState(LLFace::TEXTURE_ANIM); } - - face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); buffer->flush(); } -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) +// static +void LLDrawPoolAvatar::initSkinningMatrixPalette( + LLMatrix4* mat, + S32 count, + const LLMeshSkinInfo* skin, + LLVOAvatar *avatar) +{ + for (U32 j = 0; j < count; ++j) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (!joint) + { + joint = avatar->getJoint("mPelvis"); + } + if (joint) + { + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } +} + +// static +void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat) +{ + final_mat.clear(); + + S32 idx[4]; + + LLVector4 wght; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weights[k]; + + idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)LL_MAX_JOINTS_PER_MESH_OBJECT-1); + + wght[k] = w - floorf(w); + scale += wght[k]; + } + if (handle_bad_scale && scale <= 0.f) + { + wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f); + } + else + { + // This is enforced in unpackVolumeFaces() + llassert(scale>0.f); + wght *= 1.f/scale; + } + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mat[idx[k]], w); + + final_mat.add(src); + } +} + +bool operator==(const LLMatrix4a& a, const LLMatrix4a& b) +{ + for (S32 i=0; i<4; i++) + for (S32 j=0; j<4; j++) + { + if (a.mMatrix[i][j] != b.mMatrix[i][j]) + { + return false; + } + } + return true; +} + +bool operator!=(const LLMatrix4a& a, const LLMatrix4a& b) +{ + return !(a==b); +} + +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( + LLVOAvatar* avatar, + LLFace* face, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face) { LLVector4a* weight = vol_face.mWeights; if (!weight) @@ -1597,23 +1686,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; //build matrix palette - LLMatrix4a mp[JOINT_COUNT]; - LLMatrix4* mat = (LLMatrix4*) mp; + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); - for (U32 j = 0; j < count; ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - if (!joint) - { - joint = avatar->getJoint("mPelvis"); - } - if (joint) - { - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } + initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); @@ -1621,36 +1697,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)JOINT_COUNT-1); - - wght[k] = w - floorf(w); - scale += wght[k]; - } - // This is enforced in unpackVolumeFaces() - llassert(scale>0.f); - wght *= 1.f/scale; - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - src.setMul(mp[idx[k]], w); - - final_mat.add(src); - } - + LLMatrix4a final_mat2; + getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; @@ -1730,30 +1778,17 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (buff) { if (sShaderLevel > 0) - { //upload matrix palette to shader - LLMatrix4 mat[JOINT_COUNT]; - - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); + { + // upload matrix palette to shader + LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + initSkinningMatrixPalette(mat, count, skin, avatar); - for (U32 i = 0; i < count; ++i) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); - if (!joint) - { - joint = avatar->getJoint("mPelvis"); - } - if (joint) - { - mat[i] = skin->mInvBindMatrix[i]; - mat[i] *= joint->getWorldMatrix(); - } - } - stop_glerror(); - F32 mp[JOINT_COUNT*9]; + F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*9]; - F32 transp[JOINT_COUNT*3]; + F32 transp[LL_MAX_JOINTS_PER_MESH_OBJECT*3]; for (U32 i = 0; i < count; ++i) { diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b9d2204052..af063ee74e 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -134,6 +134,8 @@ public: void endDeferredRiggedBump(); void getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); + static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); + static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, const LLMeshSkinInfo* skin, diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 851e2d2eb7..7e5d3a9f29 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -5026,6 +5026,7 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget ) pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() ); } + //----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- @@ -5571,50 +5572,19 @@ BOOL LLModelPreview::render() //quick 'n dirty software vertex skinning //build matrix palette - - LLMatrix4 mat[64]; - for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j) - { - LLJoint* joint = getPreviewAvatar()->getJoint(model->mSkinInfo.mJointNames[j]); - if (joint) - { - mat[j] = model->mSkinInfo.mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } + + LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = llmin((U32) model->mSkinInfo.mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + LLDrawPoolAvatar::initSkinningMatrixPalette(mat, count, &model->mSkinInfo, getPreviewAvatar()); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { - LLMatrix4 final_mat; - final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f; - - LLVector4 wght; - S32 idx[4]; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j].mV[k]; + LLMatrix4a final_mata; + LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].mV, (LLMatrix4a*)mat, true, final_mata); - idx[k] = (S32) floorf(w); - wght.mV[k] = w - floorf(w); - scale += wght.mV[k]; - } - - wght *= 1.f/scale; - - for (U32 k = 0; k < 4; k++) - { - F32* src = (F32*) mat[idx[k]].mMatrix; - F32* dst = (F32*) final_mat.mMatrix; - - F32 w = wght.mV[k]; - - for (U32 l = 0; l < 16; l++) - { - dst[l] += src[l]*w; - } - } + // BENTO GROSS KLUDGERY + LLMatrix4 final_mat; + memcpy(&final_mat,&final_mata,sizeof(LLMatrix4a)); //VECTORIZE THIS LLVector3 v(face.mPositions[j].getF32ptr()); @@ -5792,7 +5762,14 @@ void LLFloaterModelPreview::refresh() } //static -void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ) +void LLModelPreview::textureLoadedCallback( + BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* src_aux, + S32 discard_level, + BOOL final, + void* userdata ) { LLModelPreview* preview = (LLModelPreview*) userdata; preview->refresh(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index eefe452c14..5e010a4712 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4164,27 +4164,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons //build matrix palette // BENTO JOINT COUNT LIMIT - static const size_t kMaxJoints = 152; + static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; - LLMatrix4a mp[kMaxJoints]; - LLMatrix4* mat = (LLMatrix4*) mp; - + LLMatrix4a mat[kMaxJoints]; U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints); - for (U32 j = 0; j < maxJoints; ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - if (!joint) - { - // Fall back to a point inside the avatar if mesh is - // rigged to an unknown joint. - joint = avatar->getJoint("mPelvis"); - } - if (joint) - { - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } + LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { @@ -4208,37 +4192,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons for (U32 j = 0; j < dst_face.mNumVertices; ++j) { LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - idx[k] = (S32) floorf(w); - wght[k] = w - floorf(w); - scale += wght[k]; - } - // This is enforced in unpackVolumeFaces() - llassert(scale>0.f); - wght *= 1.f / scale; - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - // Insure ref'd bone is in our clamped array of mats - // clamp idx to maxJoints to avoid reading garbage off stack in release - S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1); - src.setMul(mp[index], w); - final_mat.add(src); - } - + LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; -- cgit v1.2.3 From 924e4292e7a2a11ef01a5703e52116037180aa06 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 24 Sep 2015 13:29:57 -0400 Subject: SL-227 WIP - trimmed unused code. --- indra/newview/lldrawpoolavatar.cpp | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 7ccc779ba4..76c89865a5 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1600,24 +1600,6 @@ void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, boo } } -bool operator==(const LLMatrix4a& a, const LLMatrix4a& b) -{ - for (S32 i=0; i<4; i++) - for (S32 j=0; j<4; j++) - { - if (a.mMatrix[i][j] != b.mMatrix[i][j]) - { - return false; - } - } - return true; -} - -bool operator!=(const LLMatrix4a& a, const LLMatrix4a& b) -{ - return !(a==b); -} - void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLVOAvatar* avatar, LLFace* face, @@ -1697,7 +1679,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; - LLMatrix4a final_mat2; getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat); LLVector4a& v = vol_face.mPositions[j]; -- cgit v1.2.3 From 5460c0f4c80660f93723a80d464c0a5ebd97921a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 28 Sep 2015 11:53:01 -0400 Subject: SL-227 WIP - standardize usage of shared skinning code and handle additional error case in weights. --- indra/newview/lldrawpoolavatar.cpp | 23 +++++++++++++++++++---- indra/newview/llfloatermodelpreview.cpp | 32 ++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 76c89865a5..b3821fda85 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1544,6 +1544,8 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { + // BENTO - switching to use Matrix4a and SSE might speed this up. + // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); @@ -1557,6 +1559,14 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( mat[j] *= joint->getWorldMatrix(); } } + // This handles a bogus weights case that has turned up in + // practice, without the overhead of zeroing every matrix. We are + // doing this here instead of in getPerVertexSkinMatrix so the fix + // will also work in the HW skinning case. + if (count < LL_MAX_JOINTS_PER_MESH_OBJECT) + { + mat[count].setIdentity(); + } } // static @@ -1573,6 +1583,12 @@ void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, boo { F32 w = weights[k]; + // BENTO potential optimizations + // - Do clamping in unpackVolumeFaces() (once instead of every time) + // - int vs floor: if we know w is + // >= 0.0, we can use int instead of floorf; the latter + // allegedly has a lot of overhead due to ieeefp error + // checking which we should not need. idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)LL_MAX_JOINTS_PER_MESH_OBJECT-1); wght[k] = w - floorf(w); @@ -1670,7 +1686,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( //build matrix palette LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); - initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); LLMatrix4a bind_shape_matrix; @@ -1761,9 +1776,9 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (sShaderLevel > 0) { // upload matrix palette to shader - LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); - initSkinningMatrixPalette(mat, count, skin, avatar); + initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); stop_glerror(); @@ -1773,7 +1788,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) for (U32 i = 0; i < count; ++i) { - F32* m = (F32*) mat[i].mMatrix; + F32* m = (F32*) mat[i].mMatrix[0].getF32ptr(); U32 idx = i*9; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7e5d3a9f29..0736f1eac4 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -5573,26 +5573,30 @@ BOOL LLModelPreview::render() //build matrix palette - LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = llmin((U32) model->mSkinInfo.mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); - LLDrawPoolAvatar::initSkinningMatrixPalette(mat, count, &model->mSkinInfo, getPreviewAvatar()); - + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + const LLMeshSkinInfo *skin = &model->mSkinInfo; + U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, count, + skin, getPreviewAvatar()); + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { - LLMatrix4a final_mata; - LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].mV, (LLMatrix4a*)mat, true, final_mata); - - // BENTO GROSS KLUDGERY - LLMatrix4 final_mat; - memcpy(&final_mat,&final_mata,sizeof(LLMatrix4a)); + LLMatrix4a final_mat; + F32 *wptr = weight[j].mV; + LLDrawPoolAvatar::getPerVertexSkinMatrix(wptr, mat, true, final_mat); //VECTORIZE THIS - LLVector3 v(face.mPositions[j].getF32ptr()); + LLVector4a& v = face.mPositions[j]; - v = v * model->mSkinInfo.mBindShapeMatrix; - v = v * final_mat; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); - position[j] = v; + position[j][0] = dst[0]; + position[j][1] = dst[1]; + position[j][2] = dst[2]; } llassert(model->mMaterialList.size() > i); -- cgit v1.2.3 From ebad0c6868b924ba607a1b2256ae7621cab62bf4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 1 Oct 2015 11:05:29 -0400 Subject: DRTVWR-412 WIP - more work for importer merge from viewer-release --- indra/llprimitive/lldaeloader.cpp | 18 +++++----- indra/llprimitive/lldaeloader.h | 11 +++--- indra/llprimitive/llmodelloader.cpp | 63 ++++++++++++--------------------- indra/llprimitive/llmodelloader.h | 27 +++++++------- indra/newview/llfloatermodelpreview.cpp | 25 +++++++++++++ indra/newview/llfloatermodelpreview.h | 3 +- 6 files changed, 80 insertions(+), 67 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index c1b74b1fd7..6ff9613c80 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -801,15 +801,16 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector& fac // LLDAELoader //----------------------------------------------------------------------------- LLDAELoader::LLDAELoader( - std::string filename, - S32 lod, + std::string filename, + S32 lod, load_callback_t load_cb, joint_lookup_func_t joint_lookup_func, texture_load_func_t texture_load_func, - state_callback_t state_cb, - void* opaque_userdata, - JointTransformMap& jointMap, - JointSet& jointsFromNodes, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointNameSet& legalJointNames, U32 modelLimit) : LLModelLoader( filename, @@ -819,8 +820,9 @@ LLDAELoader::LLDAELoader( texture_load_func, state_cb, opaque_userdata, - jointMap, - jointsFromNodes), + jointTransformMap, + jointsFromNodes, + legalJointNames), mGeneratedModelLimit(modelLimit) { } diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 7d91a6063b..896451320c 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -47,15 +47,16 @@ public: dae_model_map mModelsMap; LLDAELoader( - std::string filename, - S32 lod, + std::string filename, + S32 lod, LLModelLoader::load_callback_t load_cb, LLModelLoader::joint_lookup_func_t joint_lookup_func, LLModelLoader::texture_load_func_t texture_load_func, LLModelLoader::state_callback_t state_cb, - void* opaque_userdata, - JointTransformMap& jointMap, - JointSet& jointsFromNodes, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointNameSet& legalJointNames, U32 modelLimit); virtual ~LLDAELoader() ; diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 81d92d151b..9cf0f10a7e 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -102,16 +102,17 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& // LLModelLoader //----------------------------------------------------------------------------- LLModelLoader::LLModelLoader( - std::string filename, - S32 lod, + std::string filename, + S32 lod, load_callback_t load_cb, joint_lookup_func_t joint_lookup_func, texture_load_func_t texture_load_func, - state_callback_t state_cb, - void* opaque_userdata, - JointTransformMap& jointMap, - JointSet& jointsFromNodes ) -: mJointList( jointMap ) + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointNameSet& legalJointNames) +: mJointList( jointTransformMap ) , mJointsFromNode( jointsFromNodes ) , LLThread("Model Loader") , mFilename(filename) @@ -127,33 +128,15 @@ LLModelLoader::LLModelLoader( , mNoOptimize(false) , mCacheOnlyHitIfRigged(false) { - mJointMap["mPelvis"] = "mPelvis"; - mJointMap["mTorso"] = "mTorso"; - mJointMap["mChest"] = "mChest"; - mJointMap["mNeck"] = "mNeck"; - mJointMap["mHead"] = "mHead"; - mJointMap["mSkull"] = "mSkull"; - mJointMap["mEyeRight"] = "mEyeRight"; - mJointMap["mEyeLeft"] = "mEyeLeft"; - mJointMap["mCollarLeft"] = "mCollarLeft"; - mJointMap["mShoulderLeft"] = "mShoulderLeft"; - mJointMap["mElbowLeft"] = "mElbowLeft"; - mJointMap["mWristLeft"] = "mWristLeft"; - mJointMap["mCollarRight"] = "mCollarRight"; - mJointMap["mShoulderRight"] = "mShoulderRight"; - mJointMap["mElbowRight"] = "mElbowRight"; - mJointMap["mWristRight"] = "mWristRight"; - mJointMap["mHipRight"] = "mHipRight"; - mJointMap["mKneeRight"] = "mKneeRight"; - mJointMap["mAnkleRight"] = "mAnkleRight"; - mJointMap["mFootRight"] = "mFootRight"; - mJointMap["mToeRight"] = "mToeRight"; - mJointMap["mHipLeft"] = "mHipLeft"; - mJointMap["mKneeLeft"] = "mKneeLeft"; - mJointMap["mAnkleLeft"] = "mAnkleLeft"; - mJointMap["mFootLeft"] = "mFootLeft"; - mJointMap["mToeLeft"] = "mToeLeft"; - + // Recognize all names we've been told are legal. + for (JointNameSet::iterator joint_name_it = legalJointNames.begin(); + joint_name_it != legalJointNames.end(); ++joint_name_it) + { + const std::string& name = *joint_name_it; + mJointMap[name] = name; + } + + // Also support various legacy aliases for commonly used joints mJointMap["avatar_mPelvis"] = "mPelvis"; mJointMap["avatar_mTorso"] = "mTorso"; mJointMap["avatar_mChest"] = "mChest"; @@ -501,8 +484,8 @@ void LLModelLoader::critiqueJointToNodeMappingFromScene( void ) //Do the actual nodes back the joint listing from the dae? //if yes then this is a fully rigged asset, otherwise it's just a partial rig - JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin(); - JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end(); + JointNameSet::iterator jointsFromNodeIt = mJointsFromNode.begin(); + JointNameSet::iterator jointsFromNodeEndIt = mJointsFromNode.end(); bool result = true; if ( !mJointsFromNode.empty() ) @@ -547,8 +530,8 @@ bool LLModelLoader::isRigLegacy( const std::vector &jointListFromAs bool result = false; - JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); - JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); + JointNameSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); + JointNameSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); @@ -581,8 +564,8 @@ bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index bb4d06dca3..894de2c76f 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -34,10 +34,10 @@ class LLJoint; -typedef std::map JointTransformMap; -typedef std::map:: iterator JointTransformMapIt; -typedef std::map JointMap; -typedef std::deque JointSet; +typedef std::map JointTransformMap; +typedef std::map::iterator JointTransformMapIt; +typedef std::map JointMap; +typedef std::deque JointNameSet; const S32 SLM_SUPPORTED_VERSION = 3; const S32 NUM_LOD = 4; @@ -116,18 +116,19 @@ public: //map of avatar joints as named in COLLADA assets to internal joint names JointMap mJointMap; JointTransformMap& mJointList; - JointSet& mJointsFromNode; + JointNameSet& mJointsFromNode; LLModelLoader( - std::string filename, - S32 lod, + std::string filename, + S32 lod, LLModelLoader::load_callback_t load_cb, LLModelLoader::joint_lookup_func_t joint_lookup_func, LLModelLoader::texture_load_func_t texture_load_func, LLModelLoader::state_callback_t state_cb, - void* opaque_userdata, - JointTransformMap& jointMap, - JointSet& jointsFromNodes); + void* opaque_userdata, + JointTransformMap& jointTransformMap, + JointNameSet& jointsFromNodes, + JointNameSet& legalJointNames); virtual ~LLModelLoader() ; virtual void setNoNormalize() { mNoNormalize = true; } @@ -189,7 +190,7 @@ protected: LLModelLoader::joint_lookup_func_t mJointLookupFunc; LLModelLoader::texture_load_func_t mTextureLoadFunc; LLModelLoader::state_callback_t mStateCallback; - void* mOpaqueData; + void* mOpaqueData; bool mRigParityWithScene; bool mRigValidJointUpload; @@ -198,8 +199,8 @@ protected: bool mNoNormalize; bool mNoOptimize; - JointSet mMasterJointList; - JointSet mMasterLegacyJointList; + JointNameSet mMasterJointList; + JointNameSet mMasterLegacyJointList; JointTransformMap mJointTransformMap; static std::list sActiveLoaderList; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index a64685f699..18a2729398 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1708,6 +1708,21 @@ void LLModelPreview::clearModel(S32 lod) mScene[lod].clear(); } +void LLModelPreview::getLegalJointNames(JointNameSet& legal_joint_names) +{ + // Get all standard skeleton joints from the preview avatar. + LLVOAvatar *av = getPreviewAvatar(); + const LLVOAvatar::avatar_joint_list_t &skel = av->getSkeleton(); + for (S32 i=0; igetName()); + } + } +} + void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm) { assert_main_thread(); @@ -1750,6 +1765,10 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable clearGLODGroup(); } + + JointNameSet legal_joint_names; + getLegalJointNames(legal_joint_names); + mModelLoader = new LLDAELoader( filename, lod, @@ -1760,6 +1779,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable this, mJointTransformMap, mJointsFromNode, + legal_joint_names, gSavedSettings.getU32("ImporterModelLimit")); if (force_disable_slm) @@ -3689,6 +3709,11 @@ BOOL LLModelPreview::render() } } + if (regen) + { + genBuffers(mPreviewLOD, skin_weight); + } + if (!skin_weight) { for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 7a518c798b..25c650a725 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -259,6 +259,7 @@ public: virtual BOOL needsRender() { return mNeedsUpdate; } void setPreviewLOD(S32 lod); void clearModel(S32 lod); + void getLegalJointNames(JointNameSet& legal_joint_names); void loadModel(std::string filename, S32 lod, bool force_disable_slm = false); void loadModelCallback(S32 lod); void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false); @@ -405,7 +406,7 @@ private: bool mLastJointUpdate; - JointSet mJointsFromNode; + JointNameSet mJointsFromNode; JointTransformMap mJointTransformMap; LLPointer mPreviewAvatar; -- cgit v1.2.3 From 4588616d0d57e744ec741ed17299c1c052d2bb55 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 2 Oct 2015 09:04:04 -0400 Subject: SL-233 FIX - removed some surplus log files. --- indra/llcharacter/llmotioncontroller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index a3532f9f9c..eabd7390b1 100755 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -789,12 +789,12 @@ void LLMotionController::updateLoadingMotions() mLoadingMotions.erase(curiter); // add motion to our loaded motion list mLoadedMotions.insert(motionp); - // FIXME SO MUCH DUMP + // FIXME BENTO SO MUCH DUMP { LLKeyframeMotion *km = dynamic_cast(motionp); if (km) { - km->dumpToFile(""); + //km->dumpToFile(""); } } // this motion should be playing -- cgit v1.2.3 From 34e48fb2f28d8ca5ea8c42b1474135c1971bdf15 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Mon, 5 Oct 2015 15:11:06 -0700 Subject: SL-225: test with joints per mesh set to 72 --- indra/llcharacter/lljoint.h | 2 +- .../app_settings/shaders/class1/avatar/objectSkinV.glsl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index b3bf588d79..1d7f4faacd 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! -const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 152; +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 72; // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index b342abb7c1..e58b19c0d0 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -27,8 +27,8 @@ ATTRIBUTE vec4 weight4; /* BENTO JOINT COUNT LIMITS * Note that the value in these two lines also needs to be updated to value-1 several places below. */ -uniform mat3 matrixPalette[152]; -uniform vec3 translationPalette[152]; +uniform mat3 matrixPalette[72]; +uniform vec3 translationPalette[72]; mat4 getObjectSkinnedTransform() { @@ -37,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(151.0)); + index = min(index, vec4(71.0)); index = max(index, vec4( 0.0)); w *= 1.0/(w.x+w.y+w.z+w.w); @@ -70,8 +70,8 @@ mat4 getObjectSkinnedTransform() // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. mat3 dummy1 = matrixPalette[0]; vec3 dummy2 = translationPalette[0]; - mat3 dummy3 = matrixPalette[151]; - vec3 dummy4 = translationPalette[151]; + mat3 dummy3 = matrixPalette[71]; + vec3 dummy4 = translationPalette[71]; #endif } -- cgit v1.2.3 From 3cc99a66e47f04e431f1431127c83e72edcea4ef Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Tue, 6 Oct 2015 07:20:56 -0700 Subject: SL-225: test with joints per mesh set to 92 --- indra/llcharacter/lljoint.h | 2 +- .../app_settings/shaders/class1/avatar/objectSkinV.glsl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 1d7f4faacd..f9b2bc419e 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! -const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 72; +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 92; // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index e58b19c0d0..c6fcc51395 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -27,8 +27,8 @@ ATTRIBUTE vec4 weight4; /* BENTO JOINT COUNT LIMITS * Note that the value in these two lines also needs to be updated to value-1 several places below. */ -uniform mat3 matrixPalette[72]; -uniform vec3 translationPalette[72]; +uniform mat3 matrixPalette[92]; +uniform vec3 translationPalette[92]; mat4 getObjectSkinnedTransform() { @@ -37,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(71.0)); + index = min(index, vec4(91.0)); index = max(index, vec4( 0.0)); w *= 1.0/(w.x+w.y+w.z+w.w); @@ -70,8 +70,8 @@ mat4 getObjectSkinnedTransform() // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. mat3 dummy1 = matrixPalette[0]; vec3 dummy2 = translationPalette[0]; - mat3 dummy3 = matrixPalette[71]; - vec3 dummy4 = translationPalette[71]; + mat3 dummy3 = matrixPalette[91]; + vec3 dummy4 = translationPalette[91]; #endif } -- cgit v1.2.3 From 389a0a8e39a04c413664802bb4471fe588790033 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Tue, 6 Oct 2015 12:51:36 -0700 Subject: SL-225: test with joints per mesh set to 112 --- indra/llcharacter/lljoint.h | 2 +- .../app_settings/shaders/class1/avatar/objectSkinV.glsl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index f9b2bc419e..b058f105d3 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! -const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 92; +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 112; // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index c6fcc51395..3d0b574234 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -27,8 +27,8 @@ ATTRIBUTE vec4 weight4; /* BENTO JOINT COUNT LIMITS * Note that the value in these two lines also needs to be updated to value-1 several places below. */ -uniform mat3 matrixPalette[92]; -uniform vec3 translationPalette[92]; +uniform mat3 matrixPalette[112]; +uniform vec3 translationPalette[112]; mat4 getObjectSkinnedTransform() { @@ -37,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(91.0)); + index = min(index, vec4(111.0)); index = max(index, vec4( 0.0)); w *= 1.0/(w.x+w.y+w.z+w.w); @@ -70,8 +70,8 @@ mat4 getObjectSkinnedTransform() // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. mat3 dummy1 = matrixPalette[0]; vec3 dummy2 = translationPalette[0]; - mat3 dummy3 = matrixPalette[91]; - vec3 dummy4 = translationPalette[91]; + mat3 dummy3 = matrixPalette[111]; + vec3 dummy4 = translationPalette[111]; #endif } -- cgit v1.2.3 From eebafb37dbb5f6d59459b68f9e88b476dc93b27a Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Tue, 6 Oct 2015 14:58:32 -0700 Subject: SL-225: test with joints per mesh set to 132 --- indra/llcharacter/lljoint.h | 2 +- indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index b058f105d3..83a203ea32 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! -const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 112; +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 132; // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 3d0b574234..67d26c34a4 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -27,8 +27,8 @@ ATTRIBUTE vec4 weight4; /* BENTO JOINT COUNT LIMITS * Note that the value in these two lines also needs to be updated to value-1 several places below. */ -uniform mat3 matrixPalette[112]; -uniform vec3 translationPalette[112]; +uniform mat3 matrixPalette[132]; +uniform vec3 translationPalette[132]; mat4 getObjectSkinnedTransform() { @@ -37,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(111.0)); + index = min(index, vec4(131.0)); index = max(index, vec4( 0.0)); w *= 1.0/(w.x+w.y+w.z+w.w); -- cgit v1.2.3 From 74b8a487646cccb3260d02910ab5b16e274ec9ab Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 7 Oct 2015 15:38:40 -0400 Subject: SL-234 WIP - adjust max mesh object joints at run-time, including rebuilding shaders --- indra/newview/app_settings/settings.xml | 11 +++++ .../shaders/class1/avatar/objectSkinV.glsl | 10 ++--- indra/newview/lldrawpoolavatar.cpp | 49 +++++++++++++++++++--- indra/newview/lldrawpoolavatar.h | 4 +- indra/newview/llfloatermodelpreview.cpp | 5 ++- indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewershadermgr.cpp | 8 +++- indra/newview/llvovolume.cpp | 5 ++- 8 files changed, 77 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6533344048..dcb2764fe7 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6112,6 +6112,17 @@ Value 1.6 + MaxJointsPerMeshObject + + Comment + Maximum joints per rigged mesh object + Persist + 1 + Type + U32 + Value + 999 + MaxPersistentNotifications Comment diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index b342abb7c1..8f754fe82b 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -27,8 +27,8 @@ ATTRIBUTE vec4 weight4; /* BENTO JOINT COUNT LIMITS * Note that the value in these two lines also needs to be updated to value-1 several places below. */ -uniform mat3 matrixPalette[152]; -uniform vec3 translationPalette[152]; +uniform mat3 matrixPalette[MAX_JOINTS_PER_MESH_OBJECT]; +uniform vec3 translationPalette[MAX_JOINTS_PER_MESH_OBJECT]; mat4 getObjectSkinnedTransform() { @@ -37,7 +37,7 @@ mat4 getObjectSkinnedTransform() vec4 w = fract(weight4); vec4 index = floor(weight4); - index = min(index, vec4(151.0)); + index = min(index, vec4(MAX_JOINTS_PER_MESH_OBJECT-1)); index = max(index, vec4( 0.0)); w *= 1.0/(w.x+w.y+w.z+w.w); @@ -70,8 +70,8 @@ mat4 getObjectSkinnedTransform() // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. mat3 dummy1 = matrixPalette[0]; vec3 dummy2 = translationPalette[0]; - mat3 dummy3 = matrixPalette[151]; - vec3 dummy4 = translationPalette[151]; + mat3 dummy3 = matrixPalette[MAX_JOINTS_PER_MESH_OBJECT-1]; + vec3 dummy4 = translationPalette[MAX_JOINTS_PER_MESH_OBJECT-1]; #endif } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b3821fda85..5d78132f6d 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1537,6 +1537,18 @@ void LLDrawPoolAvatar::getRiggedGeometry( buffer->flush(); } +// static +U32 LLDrawPoolAvatar::getMaxJointCount() +{ + return llmin(LL_MAX_JOINTS_PER_MESH_OBJECT, gSavedSettings.getU32("MaxJointsPerMeshObject")); +} + +// static +U32 LLDrawPoolAvatar::getMeshJointCount(const LLMeshSkinInfo *skin) +{ + return llmin(getMaxJointCount(), skin->mJointNames.size()); +} + // static void LLDrawPoolAvatar::initSkinningMatrixPalette( LLMatrix4* mat, @@ -1555,6 +1567,26 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( } if (joint) { +#if 0 + // BENTO HACK - test of simple push-to-ancestor complexity reduction scheme. + const std::string& name = joint->getName(); + S32 digit = name.back()-'0'; + while (joint->getParent() && (digit<=9) && (digit>=5)) + { + joint = joint->getParent(); + const std::string& name = joint->getName(); + digit = name.back()-'0'; + } + U32 j_remap = 0; + std::vector::const_iterator find_it = + std::find(skin->mJointNames.begin(), skin->mJointNames.end(), joint->getName()); + if (find_it != skin->mJointNames.end()) + { + j_remap = find_it - skin->mJointNames.begin(); + } + // BENTO for hack, use invBindMatrix of up-casted joint + mat[j] = skin->mInvBindMatrix[j_remap]; +#endif mat[j] = skin->mInvBindMatrix[j]; mat[j] *= joint->getWorldMatrix(); } @@ -1570,8 +1602,14 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( } // static -void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat) +void LLDrawPoolAvatar::getPerVertexSkinMatrix( + F32* weights, + LLMatrix4a* mat, + bool handle_bad_scale, + LLMatrix4a& final_mat, + U32 max_joints) { + final_mat.clear(); S32 idx[4]; @@ -1589,7 +1627,7 @@ void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, boo // >= 0.0, we can use int instead of floorf; the latter // allegedly has a lot of overhead due to ieeefp error // checking which we should not need. - idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)LL_MAX_JOINTS_PER_MESH_OBJECT-1); + idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)max_joints-1); wght[k] = w - floorf(w); scale += wght[k]; @@ -1685,16 +1723,17 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( //build matrix palette LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + U32 count = getMeshJointCount(skin); initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); + const U32 max_joints = getMaxJointCount(); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; - getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat); + getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; @@ -1777,7 +1816,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { // upload matrix palette to shader LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + U32 count = getMeshJointCount(skin); initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); stop_glerror(); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index af063ee74e..79d16c26bc 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -134,8 +134,10 @@ public: void endDeferredRiggedBump(); void getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); + static U32 getMaxJointCount(); + static U32 getMeshJointCount(const LLMeshSkinInfo *skin); static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); - static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat); + static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, const LLMeshSkinInfo* skin, diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 18a2729398..4267d6371e 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4028,16 +4028,17 @@ BOOL LLModelPreview::render() LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; const LLMeshSkinInfo *skin = &model->mSkinInfo; - U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT); + U32 count = LLDrawPoolAvatar::getMeshJointCount(skin); LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, getPreviewAvatar()); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); + U32 max_joints = LLDrawPoolAvatar::getMaxJointCount(); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; F32 *wptr = weight[j].mV; - LLDrawPoolAvatar::getPerVertexSkinMatrix(wptr, mat, true, final_mat); + LLDrawPoolAvatar::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints); //VECTORIZE THIS LLVector4a& v = face.mPositions[j]; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 5020518454..466edb19b2 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -761,6 +761,7 @@ void settings_setup_listeners() gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); + gSavedSettings.getControl("MaxJointsPerMeshObject")->getCommitSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index dafe2cafec..b1e521f193 100755 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -27,6 +27,8 @@ #include "llviewerprecompiledheaders.h" +#include + #include "llfeaturemanager.h" #include "llviewershadermgr.h" @@ -41,6 +43,8 @@ #include "llsky.h" #include "llvosky.h" #include "llrender.h" +#include "lljoint.h" +#include "lldrawpoolavatar.h" #ifdef LL_RELEASE_FOR_DOWNLOAD #define UNIFORM_ERRS LL_WARNS_ONCE("Shader") @@ -871,7 +875,9 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); boost::unordered_map attribs; - + attribs["MAX_JOINTS_PER_MESH_OBJECT"] = + boost::lexical_cast(LLDrawPoolAvatar::getMaxJointCount()); + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 5e010a4712..dde0e2caa1 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4167,7 +4167,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; LLMatrix4a mat[kMaxJoints]; - U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints); + U32 maxJoints = LLDrawPoolAvatar::getMeshJointCount(skin); LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) @@ -4189,10 +4189,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons { LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); + U32 max_joints = LLDrawPoolAvatar::getMaxJointCount(); for (U32 j = 0; j < dst_face.mNumVertices; ++j) { LLMatrix4a final_mat; - LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat); + LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; -- cgit v1.2.3 From 5b58bfb937f7f996c7f1b97f15b1c837aa23a463 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 7 Oct 2015 18:50:33 -0400 Subject: SL-234 WIP - mac build fix --- indra/newview/lldrawpoolavatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 5d78132f6d..e8f53e0f3d 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1546,7 +1546,7 @@ U32 LLDrawPoolAvatar::getMaxJointCount() // static U32 LLDrawPoolAvatar::getMeshJointCount(const LLMeshSkinInfo *skin) { - return llmin(getMaxJointCount(), skin->mJointNames.size()); + return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size()); } // static -- cgit v1.2.3 From 8729f5d23a52263e55df5574c672c87d00b563bd Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 13 Oct 2015 16:40:39 -0700 Subject: Bandaid for SL-202 Skin weights with joint offsets. --- indra/llprimitive/lldaeloader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 6ff9613c80..6db6bc4dc7 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1368,10 +1368,14 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); - } + } else { LL_WARNS()<<"Possibly misnamed/missing joint [" <mSkinInfo.mAlternateBindMatrix.push_back( emptyInverse ); } } -- cgit v1.2.3 From 58992e2cb4ae2787b85cff63c3ed680cd99fa8ce Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 16 Oct 2015 15:05:29 -0400 Subject: SL-234 WIP - Track which joints are part of base skeleton, remap non-base ones when not being rendered. --- indra/llappearance/llavatarappearance.cpp | 9 + indra/llcharacter/lljoint.cpp | 22 ++ indra/llcharacter/lljoint.h | 13 + indra/llprimitive/lldaeloader.cpp | 6 +- indra/llprimitive/llmodel.h | 4 +- indra/newview/app_settings/settings.xml | 11 + .../character/avatar_skeleton_tentacles.xml | 307 ++++++++++----------- indra/newview/lldrawpoolavatar.cpp | 201 ++++++++++++-- indra/newview/lldrawpoolavatar.h | 1 + 9 files changed, 401 insertions(+), 173 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index f2cd2768d8..a464ffcb43 100755 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -87,6 +87,7 @@ public: private: std::string mName; + std::string mSupport; BOOL mIsJoint; LLVector3 mPos; LLVector3 mRot; @@ -605,6 +606,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], info->mRot.mV[VZ], LLQuaternion::XYZ)); joint->setScale(info->mScale); + joint->setSupport(info->mSupport); if (info->mIsJoint) { @@ -1564,6 +1566,13 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) return FALSE; } + static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support"); + if (!node->getFastAttributeString(support_string,mSupport)) + { + LL_WARNS() << "Bone without support" << LL_ENDL; + mSupport = "base"; + } + if (mIsJoint) { static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 8fa08a2a6c..2c6278fe45 100755 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -108,6 +108,7 @@ void LLJoint::init() mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; + mSupport = SUPPORT_BASE; } LLJoint::LLJoint() : @@ -169,6 +170,27 @@ void LLJoint::setup(const std::string &name, LLJoint *parent) } } +//----------------------------------------------------------------------------- +// setSupport() +//----------------------------------------------------------------------------- +void LLJoint::setSupport(const std::string& support_name) +{ + if (support_name == "extended") + { + setSupport(SUPPORT_EXTENDED); + } + else if (support_name == "base") + { + setSupport(SUPPORT_BASE); + } + else + { + LL_WARNS() << "unknown support string " << support_name << LL_ENDL; + setSupport(SUPPORT_BASE); + } +} + + //----------------------------------------------------------------------------- // touch() // Sets all dirty flags for all children, recursively. diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index b3bf588d79..de61d56101 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -91,9 +91,17 @@ public: POSITION_DIRTY = 0x1 << 2, ALL_DIRTY = 0x7 }; +public: + enum SupportCategory + { + SUPPORT_BASE, + SUPPORT_EXTENDED + }; protected: std::string mName; + SupportCategory mSupport; + // parent joint LLJoint *mParent; @@ -144,6 +152,11 @@ public: const std::string& getName() const { return mName; } void setName( const std::string &name ) { mName = name; } + // get/set support + SupportCategory getSupport() const { return mSupport; } + void setSupport( const SupportCategory& support) { mSupport = support; } + void setSupport( const std::string& support_string); + // getParent LLJoint *getParent() { return mParent; } diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 6ff9613c80..e7fbbba84e 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1257,7 +1257,8 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do name = mJointMap[name]; } model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; + // BENTO this does not appear to be used anywhere. + // model->mSkinInfo.mJointMap[name] = j; } } else @@ -1275,7 +1276,8 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do name = mJointMap[name]; } model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; + // BENTO not used? + // model->mSkinInfo.mJointMap[name] = j; } } } diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index ae602c09df..56844ac16d 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -46,7 +46,9 @@ public: std::vector mJointNames; std::vector mInvBindMatrix; std::vector mAlternateBindMatrix; - std::map mJointMap; + std::vector mJointRemap; + // BENTO not used? + //std::map mJointMap; LLMeshSkinInfo() { } LLMeshSkinInfo(LLSD& data); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 133e51b531..8bf91c0f1e 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3492,6 +3492,17 @@ Value 0 + IncludeEnhancedSkeleton + + Comment + Include extended skeleton joints when rendering skinned meshes. + Persist + 1 + Type + Boolean + Value + 1 + MinObjectsForUnlinkConfirm Comment diff --git a/indra/newview/character/avatar_skeleton_tentacles.xml b/indra/newview/character/avatar_skeleton_tentacles.xml index 9863a5cbfd..929feaf25c 100644 --- a/indra/newview/character/avatar_skeleton_tentacles.xml +++ b/indra/newview/character/avatar_skeleton_tentacles.xml @@ -1,64 +1,63 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + @@ -69,16 +68,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -89,16 +88,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -109,16 +108,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -129,16 +128,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -149,16 +148,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -169,16 +168,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -189,16 +188,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -209,16 +208,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -229,16 +228,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -251,27 +250,27 @@ - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index e8f53e0f3d..987a15c72d 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1549,6 +1549,156 @@ U32 LLDrawPoolAvatar::getMeshJointCount(const LLMeshSkinInfo *skin) return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size()); } +bool getNameIndex(const std::string& name, std::vector& names, U32& result) +{ + std::vector::const_iterator find_it = + std::find(names.begin(), names.end(), name); + if (find_it != names.end()) + { + result = find_it - names.begin(); + return true; + } + else + { + return false; + } +} + +// Find a name table index that is also a valid joint on the +// avatar. Order of preference is: requested name, mPelvis, first +// valid match in names table. +U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector& joint_names) +{ + U32 result; + if (avatar->getJoint(name) && getNameIndex(name,joint_names,result)) + { + return result; + } + if (getNameIndex("mPelvis",joint_names,result)) + { + return result; + } + for (U32 j=0; jgetJoint(joint_names[j])) + { + return j; + } + } + // BENTO how to handle? + LL_ERRS() << "no valid joints in joint_names" << LL_ENDL; + return 0; +} + +// Which joint will stand in for this joint? +U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector& joint_names) +{ +#if 1 + bool include_enhanced = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); + U32 j_proxy = getValidJointIndex(joint_names[joint_index], avatar, joint_names); + LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); + llassert(joint); + // BENTO - test of simple push-to-base-ancestor + // complexity reduction scheme. Find the first + // ancestor that's not flagged as extended, or the + // last ancestor that's rigged in this mesh, whichever + // comes first. + while (1) + { + if (include_enhanced || + joint->getSupport()==LLJoint::SUPPORT_BASE) + break; + LLJoint *parent = joint->getParent(); + if (!parent) + break; + if (!getNameIndex(parent->getName(), joint_names, j_proxy)) + { + break; + } + joint = parent; + } + return j_proxy; +#else + return 0; +#endif +} + +// static + +// Destructively remap the joints in skin info based on what joints +// are known in the avatar, and which are currently supported. This +// will also populate mJointRemap[] in the skin, which can be used to +// make the corresponding changes to the integer part of vertex +// weights. +// +// This will throw away joint info for any joints that are not known +// in the avatar, or not currently flagged to support based on the +// debug setting for IncludeEnhancedSkeleton. +void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) +{ + // skip if already done. + if (!skin->mJointRemap.empty()) + { + return; + } + + // Compute the remap + std::vector j_proxy(skin->mJointNames.size()); + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + U32 j_rep = getProxyJointIndex(j, avatar, skin->mJointNames); + j_proxy[j] = j_rep; + } + S32 top = 0; + std::vector j_remap(skin->mJointNames.size()); + // Fill in j_remap for all joints that will make the cut. + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] == j) + { + // Joint will be included + j_remap[j] = top++; + } + } + // Then use j_proxy to fill in j_remap for the joints that will be discarded + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] != j) + { + j_remap[j] = j_remap[j_proxy[j]]; + } + } + + + // Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix + std::vector new_joint_names; + std::vector new_inv_bind_matrix; + std::vector new_alternate_bind_matrix; + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] == j) + { + new_joint_names.push_back(skin->mJointNames[j]); + new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]); + if (!skin->mAlternateBindMatrix.empty()) + { + new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]); + } + } + } + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LL_INFOS() << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL; + } + + //skin->mJointNames = new_joint_names; + //skin->mInvBindMatrix = new_inv_bind_matrix; + //skin->mAlternateBindMatrix = new_alternate_bind_matrix; + skin->mJointRemap = j_remap; +} + // static void LLDrawPoolAvatar::initSkinningMatrixPalette( LLMatrix4* mat, @@ -1556,38 +1706,57 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { + // BENTO ugly const cast + remapSkinInfoJoints(avatar, const_cast(skin)); + // BENTO - switching to use Matrix4a and SSE might speed this up. // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); +#if 1 // Don't need this stuff if we've already remapped/cleaned up above if (!joint) { joint = avatar->getJoint("mPelvis"); } if (joint) { -#if 0 - // BENTO HACK - test of simple push-to-ancestor complexity reduction scheme. - const std::string& name = joint->getName(); - S32 digit = name.back()-'0'; - while (joint->getParent() && (digit<=9) && (digit>=5)) + if (!gSavedSettings.getBOOL("IncludeEnhancedSkeleton")) { - joint = joint->getParent(); - const std::string& name = joint->getName(); - digit = name.back()-'0'; + // BENTO - test of simple push-to-base-ancestor + // complexity reduction scheme. Find the first + // ancestor that's not flagged as extended, or the + // last ancestor that's rigged in this mesh, whichever + // comes first. + U32 j_remap = 0; + while (1) + { + if (joint->getSupport()==LLJoint::SUPPORT_BASE) + break; + LLJoint *parent = joint->getParent(); + if (!parent) + break; + std::vector::const_iterator find_it = + std::find(skin->mJointNames.begin(), skin->mJointNames.end(), parent->getName()); + if (find_it != skin->mJointNames.end()) + { + j_remap = find_it - skin->mJointNames.begin(); + } + else + { + break; + } + joint = parent; + } + mat[j] = skin->mInvBindMatrix[j_remap]; } - U32 j_remap = 0; - std::vector::const_iterator find_it = - std::find(skin->mJointNames.begin(), skin->mJointNames.end(), joint->getName()); - if (find_it != skin->mJointNames.end()) + else { - j_remap = find_it - skin->mJointNames.begin(); + mat[j] = skin->mInvBindMatrix[j]; } - // BENTO for hack, use invBindMatrix of up-casted joint - mat[j] = skin->mInvBindMatrix[j_remap]; -#endif +#else mat[j] = skin->mInvBindMatrix[j]; +#endif mat[j] *= joint->getWorldMatrix(); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 79d16c26bc..27d4c949fd 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -136,6 +136,7 @@ public: void getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); static U32 getMaxJointCount(); static U32 getMeshJointCount(const LLMeshSkinInfo *skin); + static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, -- cgit v1.2.3 From 6c6a95478ecd657c271354d93a6f98c90093bac5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 19 Oct 2015 16:32:49 -0400 Subject: SL-234 WIP - remap skin weights to match included-joint logic --- indra/llmath/llvolume.cpp | 1 + indra/llmath/llvolume.h | 4 ++ indra/newview/lldrawpoolavatar.cpp | 113 ++++++++++++++++++------------------- indra/newview/lldrawpoolavatar.h | 2 + indra/newview/llvovolume.cpp | 1 + 5 files changed, 64 insertions(+), 57 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8608e45a91..206330fd53 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4568,6 +4568,7 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), + mWeightsRemapped(FALSE), mOctree(NULL), mOptimized(FALSE) { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1da2d0c6b1..33e1403a14 100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -953,6 +953,10 @@ public: // mWeights.size() should be empty or match mVertices.size() LLVector4a* mWeights; + // Whether or not the weights have been cleaned up and remapped + // based on currently supported joints. + mutable BOOL mWeightsRemapped; + LLOctreeNode* mOctree; //whether or not face has been cache optimized diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 987a15c72d..dff6cada9a 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1593,7 +1593,6 @@ U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector< // Which joint will stand in for this joint? U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector& joint_names) { -#if 1 bool include_enhanced = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); U32 j_proxy = getValidJointIndex(joint_names[joint_index], avatar, joint_names); LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); @@ -1618,9 +1617,6 @@ U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector " << new_joint_names[j_remap[j]] << LL_ENDL; } - //skin->mJointNames = new_joint_names; - //skin->mInvBindMatrix = new_inv_bind_matrix; - //skin->mAlternateBindMatrix = new_alternate_bind_matrix; + skin->mJointNames = new_joint_names; + skin->mInvBindMatrix = new_inv_bind_matrix; + skin->mAlternateBindMatrix = new_alternate_bind_matrix; skin->mJointRemap = j_remap; } @@ -1706,67 +1704,59 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { - // BENTO ugly const cast - remapSkinInfoJoints(avatar, const_cast(skin)); - // BENTO - switching to use Matrix4a and SSE might speed this up. // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); -#if 1 // Don't need this stuff if we've already remapped/cleaned up above - if (!joint) + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } +} + +// Transform the weights based on the remap info stored in skin. Note +// that this is destructive and non-idempotent, so we need to keep +// track of whether we've done it already. If the desired remapping +// changes, the viewer must be restarted. +// +// static +void LLDrawPoolAvatar::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ + llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for. + const U32* remap = &skin->mJointRemap[0]; + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; jgetJoint("mPelvis"); + S32 i = llfloor(w[k]); + F32 f = w[k]-i; + i = llclamp(i,0,max_joints-1); + w[k] = remap[i] + f; } - if (joint) + } +} + +// static +void LLDrawPoolAvatar::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ + if (skin->mJointRemap.size()>0) + { + // Check the weights are consistent with the current remap. + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; jgetSupport()==LLJoint::SUPPORT_BASE) - break; - LLJoint *parent = joint->getParent(); - if (!parent) - break; - std::vector::const_iterator find_it = - std::find(skin->mJointNames.begin(), skin->mJointNames.end(), parent->getName()); - if (find_it != skin->mJointNames.end()) - { - j_remap = find_it - skin->mJointNames.begin(); - } - else - { - break; - } - joint = parent; - } - mat[j] = skin->mInvBindMatrix[j_remap]; - } - else + F32 *w = weights[j].getF32ptr(); + + for (U32 k=0; k<4; ++k) { - mat[j] = skin->mInvBindMatrix[j]; + S32 i = llfloor(w[k]); + llassert(i>=0); + llassert(imInvBindMatrix[j]; -#endif - mat[j] *= joint->getWorldMatrix(); - } } - // This handles a bogus weights case that has turned up in - // practice, without the overhead of zeroing every matrix. We are - // doing this here instead of in getPerVertexSkinMatrix so the fix - // will also work in the HW skinning case. - if (count < LL_MAX_JOINTS_PER_MESH_OBJECT) - { - mat[count].setIdentity(); } } @@ -1835,12 +1825,20 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( { return; } + // BENTO ugly const cast + remapSkinInfoJoints(avatar, const_cast(skin)); LLPointer buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); U32 data_mask = face->getRiggedVertexBufferDataMask(); + if (!vol_face.mWeightsRemapped) + { + remapSkinWeights(weight, vol_face.mNumVertices, skin); + vol_face.mWeightsRemapped = TRUE; + } + if (buffer.isNull() || buffer->getTypeMask() != data_mask || buffer->getNumVerts() != vol_face.mNumVertices || @@ -1894,6 +1892,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; U32 count = getMeshJointCount(skin); initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); + checkSkinWeights(weight, buffer->getNumVerts(), skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 27d4c949fd..8d6e95ba1a 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -138,6 +138,8 @@ public: static U32 getMeshJointCount(const LLMeshSkinInfo *skin); static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); + static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c09786b7c7..5d8558cb46 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4192,6 +4192,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if ( weight ) { + LLDrawPoolAvatar::checkSkinWeights(weight, dst_face.mNumVertices, skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); -- cgit v1.2.3 From cb0031880d72cde1d129175276391e91ddadae66 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Tue, 20 Oct 2015 09:22:47 -0700 Subject: SL-113: viewer message from simulator on illegal attachment point --- indra/newview/skins/default/xui/en/notifications.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f847c73287..30e7caad76 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10258,6 +10258,14 @@ Not enough script resources available to attach object! Cannot attach object because it is already being removed. + + fail + The attachment point specified is not valid and the item has been attached to the default location: chest. + + Date: Wed, 21 Oct 2015 16:47:03 -0400 Subject: SL-234 WIP - moved LLSkinningUtil funcs to separate class/files. Remap weights where needed. Warn that related debug settings require restart to take effect. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llappviewer.cpp | 4 + indra/newview/lldrawpoolavatar.cpp | 295 +----------------- indra/newview/lldrawpoolavatar.h | 7 - indra/newview/llfloatermodelpreview.cpp | 10 +- indra/newview/llskinningutil.cpp | 329 +++++++++++++++++++++ indra/newview/llskinningutil.h | 51 ++++ indra/newview/llviewercontrol.cpp | 10 +- indra/newview/llviewershadermgr.cpp | 4 +- indra/newview/llvovolume.cpp | 11 +- .../newview/skins/default/xui/en/notifications.xml | 7 + 11 files changed, 425 insertions(+), 305 deletions(-) create mode 100644 indra/newview/llskinningutil.cpp create mode 100644 indra/newview/llskinningutil.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 16877c345e..4ba81047f5 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -541,6 +541,7 @@ set(viewer_SOURCE_FILES llsidepaneliteminfo.cpp llsidepaneltaskinfo.cpp llsidetraypanelcontainer.cpp + llskinningutil.cpp llsky.cpp llslurl.cpp llsnapshotlivepreview.cpp @@ -1147,6 +1148,7 @@ set(viewer_HEADER_FILES llsidepaneliteminfo.h llsidepaneltaskinfo.h llsidetraypanelcontainer.h + llskinningutil.h llsky.h llslurl.h llsnapshotlivepreview.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fbf2a04bcc..04758ef839 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -101,6 +101,7 @@ #include "llscenemonitor.h" #include "llavatarrenderinfoaccountant.h" #include "lllocalbitmaps.h" +#include "llskinningutil.h" // Linden library includes #include "llavatarnamecache.h" @@ -794,6 +795,9 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; + // initialize skinning util + LLSkinningUtil::initClass(); + //set the max heap size. initMaxHeapSize() ; LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index dff6cada9a..89233b8e32 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "lldrawpoolavatar.h" +#include "llskinningutil.h" #include "llrender.h" #include "llvoavatar.h" @@ -1537,282 +1538,6 @@ void LLDrawPoolAvatar::getRiggedGeometry( buffer->flush(); } -// static -U32 LLDrawPoolAvatar::getMaxJointCount() -{ - return llmin(LL_MAX_JOINTS_PER_MESH_OBJECT, gSavedSettings.getU32("MaxJointsPerMeshObject")); -} - -// static -U32 LLDrawPoolAvatar::getMeshJointCount(const LLMeshSkinInfo *skin) -{ - return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size()); -} - -bool getNameIndex(const std::string& name, std::vector& names, U32& result) -{ - std::vector::const_iterator find_it = - std::find(names.begin(), names.end(), name); - if (find_it != names.end()) - { - result = find_it - names.begin(); - return true; - } - else - { - return false; - } -} - -// Find a name table index that is also a valid joint on the -// avatar. Order of preference is: requested name, mPelvis, first -// valid match in names table. -U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector& joint_names) -{ - U32 result; - if (avatar->getJoint(name) && getNameIndex(name,joint_names,result)) - { - return result; - } - if (getNameIndex("mPelvis",joint_names,result)) - { - return result; - } - for (U32 j=0; jgetJoint(joint_names[j])) - { - return j; - } - } - // BENTO how to handle? - LL_ERRS() << "no valid joints in joint_names" << LL_ENDL; - return 0; -} - -// Which joint will stand in for this joint? -U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector& joint_names) -{ - bool include_enhanced = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); - U32 j_proxy = getValidJointIndex(joint_names[joint_index], avatar, joint_names); - LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); - llassert(joint); - // BENTO - test of simple push-to-base-ancestor - // complexity reduction scheme. Find the first - // ancestor that's not flagged as extended, or the - // last ancestor that's rigged in this mesh, whichever - // comes first. - while (1) - { - if (include_enhanced || - joint->getSupport()==LLJoint::SUPPORT_BASE) - break; - LLJoint *parent = joint->getParent(); - if (!parent) - break; - if (!getNameIndex(parent->getName(), joint_names, j_proxy)) - { - break; - } - joint = parent; - } - return j_proxy; -} - -// static - -// Destructively remap the joints in skin info based on what joints -// are known in the avatar, and which are currently supported. This -// will also populate mJointRemap[] in the skin, which can be used to -// make the corresponding changes to the integer part of vertex -// weights. -// -// This will throw away joint info for any joints that are not known -// in the avatar, or not currently flagged to support based on the -// debug setting for IncludeEnhancedSkeleton. -// -// static -void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) -{ - // skip if already done. - if (!skin->mJointRemap.empty()) - { - return; - } - - // Compute the remap - std::vector j_proxy(skin->mJointNames.size()); - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - U32 j_rep = getProxyJointIndex(j, avatar, skin->mJointNames); - j_proxy[j] = j_rep; - } - S32 top = 0; - std::vector j_remap(skin->mJointNames.size()); - // Fill in j_remap for all joints that will make the cut. - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] == j) - { - // Joint will be included - j_remap[j] = top++; - } - } - // Then use j_proxy to fill in j_remap for the joints that will be discarded - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] != j) - { - j_remap[j] = j_remap[j_proxy[j]]; - } - } - - - // Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix - std::vector new_joint_names; - std::vector new_inv_bind_matrix; - std::vector new_alternate_bind_matrix; - - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] == j) - { - new_joint_names.push_back(skin->mJointNames[j]); - new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]); - if (!skin->mAlternateBindMatrix.empty()) - { - new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]); - } - } - } - - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - LL_INFOS() << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL; - } - - skin->mJointNames = new_joint_names; - skin->mInvBindMatrix = new_inv_bind_matrix; - skin->mAlternateBindMatrix = new_alternate_bind_matrix; - skin->mJointRemap = j_remap; -} - -// static -void LLDrawPoolAvatar::initSkinningMatrixPalette( - LLMatrix4* mat, - S32 count, - const LLMeshSkinInfo* skin, - LLVOAvatar *avatar) -{ - // BENTO - switching to use Matrix4a and SSE might speed this up. - // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. - for (U32 j = 0; j < count; ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } -} - -// Transform the weights based on the remap info stored in skin. Note -// that this is destructive and non-idempotent, so we need to keep -// track of whether we've done it already. If the desired remapping -// changes, the viewer must be restarted. -// -// static -void LLDrawPoolAvatar::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) -{ - llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for. - const U32* remap = &skin->mJointRemap[0]; - const S32 max_joints = skin->mJointNames.size(); - for (U32 j=0; jmJointRemap.size()>0) - { - // Check the weights are consistent with the current remap. - const S32 max_joints = skin->mJointNames.size(); - for (U32 j=0; j=0); - llassert(i= 0.0, we can use int instead of floorf; the latter - // allegedly has a lot of overhead due to ieeefp error - // checking which we should not need. - idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)max_joints-1); - - wght[k] = w - floorf(w); - scale += wght[k]; - } - if (handle_bad_scale && scale <= 0.f) - { - wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f); - } - else - { - // This is enforced in unpackVolumeFaces() - llassert(scale>0.f); - wght *= 1.f/scale; - } - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - src.setMul(mat[idx[k]], w); - - final_mat.add(src); - } -} - void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLVOAvatar* avatar, LLFace* face, @@ -1826,7 +1551,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( return; } // BENTO ugly const cast - remapSkinInfoJoints(avatar, const_cast(skin)); + LLSkinningUtil::remapSkinInfoJoints(avatar, const_cast(skin)); LLPointer buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); @@ -1835,7 +1560,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( if (!vol_face.mWeightsRemapped) { - remapSkinWeights(weight, vol_face.mNumVertices, skin); + LLSkinningUtil::remapSkinWeights(weight, vol_face.mNumVertices, skin); vol_face.mWeightsRemapped = TRUE; } @@ -1890,18 +1615,18 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( //build matrix palette LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = getMeshJointCount(skin); - initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); - checkSkinWeights(weight, buffer->getNumVerts(), skin); + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); + LLSkinningUtil::checkSkinWeights(weight, buffer->getNumVerts(), skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); - const U32 max_joints = getMaxJointCount(); + const U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; - getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; @@ -1984,8 +1709,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { // upload matrix palette to shader LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = getMeshJointCount(skin); - initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); stop_glerror(); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 8d6e95ba1a..b9d2204052 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -134,13 +134,6 @@ public: void endDeferredRiggedBump(); void getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); - static U32 getMaxJointCount(); - static U32 getMeshJointCount(const LLMeshSkinInfo *skin); - static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); - static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); - static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); - static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); - static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, const LLMeshSkinInfo* skin, diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c971faac5f..3cad7badad 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -42,7 +42,6 @@ #include "llcombobox.h" #include "lldatapacker.h" #include "lldrawable.h" -#include "lldrawpoolavatar.h" #include "llrender.h" #include "llface.h" #include "lleconomy.h" @@ -54,6 +53,7 @@ #include "llmeshrepository.h" #include "llnotificationsutil.h" #include "llsdutil_math.h" +#include "llskinningutil.h" #include "lltextbox.h" #include "lltoolmgr.h" #include "llui.h" @@ -4031,17 +4031,17 @@ BOOL LLModelPreview::render() LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; const LLMeshSkinInfo *skin = &model->mSkinInfo; - U32 count = LLDrawPoolAvatar::getMeshJointCount(skin); - LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, count, + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, getPreviewAvatar()); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); - U32 max_joints = LLDrawPoolAvatar::getMaxJointCount(); + U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { LLMatrix4a final_mat; F32 *wptr = weight[j].mV; - LLDrawPoolAvatar::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints); + LLSkinningUtil::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints); //VECTORIZE THIS LLVector4a& v = face.mPositions[j]; diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp new file mode 100644 index 0000000000..23bbbdcf90 --- /dev/null +++ b/indra/newview/llskinningutil.cpp @@ -0,0 +1,329 @@ +/** +* @file llskinningutil.cpp +* @brief Functions for mesh object skinning +* @author vir@lindenlab.com +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 "llskinningutil.h" +#include "llvoavatar.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" + +bool LLSkinningUtil::sIncludeEnhancedSkeleton = true; +U32 LLSkinningUtil::sMaxJointsPerMeshObject = LL_MAX_JOINTS_PER_MESH_OBJECT; + +namespace { + +bool get_name_index(const std::string& name, std::vector& names, U32& result) +{ + std::vector::const_iterator find_it = + std::find(names.begin(), names.end(), name); + if (find_it != names.end()) + { + result = find_it - names.begin(); + return true; + } + else + { + return false; + } +} + +// Find a name table index that is also a valid joint on the +// avatar. Order of preference is: requested name, mPelvis, first +// valid match in names table. +U32 get_valid_joint_index(const std::string& name, LLVOAvatar *avatar, std::vector& joint_names) +{ + U32 result; + if (avatar->getJoint(name) && get_name_index(name,joint_names,result)) + { + return result; + } + if (get_name_index("mPelvis",joint_names,result)) + { + return result; + } + for (U32 j=0; jgetJoint(joint_names[j])) + { + return j; + } + } + // BENTO how to handle? + LL_ERRS() << "no valid joints in joint_names" << LL_ENDL; + return 0; +} + +// Which joint will stand in for this joint? +U32 get_proxy_joint_index(U32 joint_index, LLVOAvatar *avatar, std::vector& joint_names) +{ + bool include_enhanced = LLSkinningUtil::sIncludeEnhancedSkeleton; + U32 j_proxy = get_valid_joint_index(joint_names[joint_index], avatar, joint_names); + LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); + llassert(joint); + // BENTO - test of simple push-to-base-ancestor + // complexity reduction scheme. Find the first + // ancestor that's not flagged as extended, or the + // last ancestor that's rigged in this mesh, whichever + // comes first. + while (1) + { + if (include_enhanced || + joint->getSupport()==LLJoint::SUPPORT_BASE) + break; + LLJoint *parent = joint->getParent(); + if (!parent) + break; + if (!get_name_index(parent->getName(), joint_names, j_proxy)) + { + break; + } + joint = parent; + } + return j_proxy; +} + +} + +// static +void LLSkinningUtil::initClass() +{ + sIncludeEnhancedSkeleton = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); + sMaxJointsPerMeshObject = gSavedSettings.getU32("MaxJointsPerMeshObject"); +} + +// static +U32 LLSkinningUtil::getMaxJointCount() +{ + U32 result = llmin(LL_MAX_JOINTS_PER_MESH_OBJECT, sMaxJointsPerMeshObject); + if (!sIncludeEnhancedSkeleton) + { + result = llmin(result,(U32)52); // BENTO replace with LLAvatarAppearance::getBaseJointCount()) or equivalent + } + return result; +} + +// static +U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin) +{ + return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size()); +} + +// static + +// Destructively remap the joints in skin info based on what joints +// are known in the avatar, and which are currently supported. This +// will also populate mJointRemap[] in the skin, which can be used to +// make the corresponding changes to the integer part of vertex +// weights. +// +// This will throw away joint info for any joints that are not known +// in the avatar, or not currently flagged to support based on the +// debug setting for IncludeEnhancedSkeleton. +// +// static +void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) +{ + // skip if already done. + if (!skin->mJointRemap.empty()) + { + return; + } + + // Compute the remap + std::vector j_proxy(skin->mJointNames.size()); + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + U32 j_rep = get_proxy_joint_index(j, avatar, skin->mJointNames); + j_proxy[j] = j_rep; + } + S32 top = 0; + std::vector j_remap(skin->mJointNames.size()); + // Fill in j_remap for all joints that will make the cut. + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] == j) + { + // Joint will be included + j_remap[j] = top++; + } + } + // Then use j_proxy to fill in j_remap for the joints that will be discarded + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] != j) + { + j_remap[j] = j_remap[j_proxy[j]]; + } + } + + + // Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix + std::vector new_joint_names; + std::vector new_inv_bind_matrix; + std::vector new_alternate_bind_matrix; + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + if (j_proxy[j] == j) + { + new_joint_names.push_back(skin->mJointNames[j]); + new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]); + if (!skin->mAlternateBindMatrix.empty()) + { + new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]); + } + } + } + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LL_DEBUGS("Avatar") << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL; + } + + skin->mJointNames = new_joint_names; + skin->mInvBindMatrix = new_inv_bind_matrix; + skin->mAlternateBindMatrix = new_alternate_bind_matrix; + skin->mJointRemap = j_remap; +} + +// static +void LLSkinningUtil::initSkinningMatrixPalette( + LLMatrix4* mat, + S32 count, + const LLMeshSkinInfo* skin, + LLVOAvatar *avatar) +{ + // BENTO - switching to use Matrix4a and SSE might speed this up. + // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. + for (U32 j = 0; j < count; ++j) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } +} + +// Transform the weights based on the remap info stored in skin. Note +// that this is destructive and non-idempotent, so we need to keep +// track of whether we've done it already. If the desired remapping +// changes, the viewer must be restarted. +// +// static +void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ + llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for. + const U32* remap = &skin->mJointRemap[0]; + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; jmJointRemap.size()>0) + { + // Check the weights are consistent with the current remap. + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; j=0); + llassert(i= 0.0, we can use int instead of floorf; the latter + // allegedly has a lot of overhead due to ieeefp error + // checking which we should not need. + idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)max_joints-1); + + wght[k] = w - floorf(w); + scale += wght[k]; + } + if (handle_bad_scale && scale <= 0.f) + { + wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f); + } + else + { + // This is enforced in unpackVolumeFaces() + llassert(scale>0.f); + wght *= 1.f/scale; + } + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mat[idx[k]], w); + + final_mat.add(src); + } +} + diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h new file mode 100644 index 0000000000..813d401535 --- /dev/null +++ b/indra/newview/llskinningutil.h @@ -0,0 +1,51 @@ +/** +* @file llskinningutil.h +* @brief Functions for mesh object skinning +* @author vir@lindenlab.com +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 LLSKINNINGUTIL_H +#define LLSKINNINGUTIL_H + +class LLVOAvatar; +class LLMeshSkinInfo; +class LLMatrix4a; + +class LLSkinningUtil +{ +public: + static void initClass(); + static U32 getMaxJointCount(); + static U32 getMeshJointCount(const LLMeshSkinInfo *skin); + static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); + static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); + static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); + + // This is initialized from gSavedSettings at startup and then left alone. + static bool sIncludeEnhancedSkeleton; + static U32 sMaxJointsPerMeshObject; +}; + +#endif diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 466edb19b2..4e4aaf5f8e 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -67,6 +67,7 @@ #include "llvowlsky.h" #include "llrender.h" #include "llnavigationbar.h" +#include "llnotificationsutil.h" #include "llfloatertools.h" #include "llpaneloutfitsinventory.h" #include "llpanellogin.h" @@ -119,6 +120,12 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue) } +static bool handleDeferredDebugSettingChanged(const LLSD& newvalue) +{ + LLNotificationsUtil::add("ChangeDeferredDebugSetting"); + return true; +} + static bool handleSetShaderChanged(const LLSD& newvalue) { // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache @@ -761,7 +768,8 @@ void settings_setup_listeners() gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); - gSavedSettings.getControl("MaxJointsPerMeshObject")->getCommitSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); + gSavedSettings.getControl("MaxJointsPerMeshObject")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2)); + gSavedSettings.getControl("IncludeEnhancedSkeleton")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index b1e521f193..3e0cec0f09 100755 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -44,7 +44,7 @@ #include "llvosky.h" #include "llrender.h" #include "lljoint.h" -#include "lldrawpoolavatar.h" +#include "llskinningutil.h" #ifdef LL_RELEASE_FOR_DOWNLOAD #define UNIFORM_ERRS LL_WARNS_ONCE("Shader") @@ -876,7 +876,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() boost::unordered_map attribs; attribs["MAX_JOINTS_PER_MESH_OBJECT"] = - boost::lexical_cast(LLDrawPoolAvatar::getMaxJointCount()); + boost::lexical_cast(LLSkinningUtil::getMaxJointCount()); // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 5d8558cb46..9b2e9db59a 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -54,6 +54,7 @@ #include "llspatialpartition.h" #include "llhudmanager.h" #include "llflexibleobject.h" +#include "llskinningutil.h" #include "llsky.h" #include "lltexturefetch.h" #include "llvector4a.h" @@ -4179,8 +4180,8 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; LLMatrix4a mat[kMaxJoints]; - U32 maxJoints = LLDrawPoolAvatar::getMeshJointCount(skin); - LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); + U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { @@ -4192,7 +4193,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if ( weight ) { - LLDrawPoolAvatar::checkSkinWeights(weight, dst_face.mNumVertices, skin); + LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); @@ -4202,11 +4203,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons { LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); - U32 max_joints = LLDrawPoolAvatar::getMaxJointCount(); + U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < dst_face.mNumVertices; ++j) { LLMatrix4a final_mat; - LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; LLVector4a t; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 70ba4d5077..ab027ac600 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1422,6 +1422,13 @@ Note: This will clear the cache. Port settings take effect after you restart [APP_NAME]. + +This debug setting change will take effect after you restart [APP_NAME]. + + Date: Wed, 21 Oct 2015 19:20:28 -0400 Subject: SL-234 WIP - TC build fixes --- indra/newview/llskinningutil.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 23bbbdcf90..bcbeee6958 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -256,22 +256,24 @@ void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, con // static void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) { +#ifndef LL_RELEASE_FOR_DOWNLOAD + const S32 max_joints = skin->mJointNames.size(); if (skin->mJointRemap.size()>0) { // Check the weights are consistent with the current remap. - const S32 max_joints = skin->mJointNames.size(); for (U32 j=0; j=0); llassert(i Date: Thu, 22 Oct 2015 11:23:36 -0400 Subject: SL-234 WIP - fix for enforcement of MaxJointsPerMeshObject limit --- indra/newview/llskinningutil.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index bcbeee6958..5fd2248060 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -154,6 +154,8 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski return; } + U32 max_joints = getMeshJointCount(skin); + // Compute the remap std::vector j_proxy(skin->mJointNames.size()); for (U32 j = 0; j < skin->mJointNames.size(); ++j) @@ -163,13 +165,19 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski } S32 top = 0; std::vector j_remap(skin->mJointNames.size()); - // Fill in j_remap for all joints that will make the cut. + // Fill in j_remap for all joints that will be kept. for (U32 j = 0; j < skin->mJointNames.size(); ++j) { if (j_proxy[j] == j) { // Joint will be included - j_remap[j] = top++; + j_remap[j] = top; + if (top < max_joints-1) + { + top++; + } + + } } // Then use j_proxy to fill in j_remap for the joints that will be discarded @@ -189,7 +197,7 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski for (U32 j = 0; j < skin->mJointNames.size(); ++j) { - if (j_proxy[j] == j) + if (j_proxy[j] == j && new_joint_names.size() < max_joints) { new_joint_names.push_back(skin->mJointNames[j]); new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]); @@ -199,6 +207,7 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski } } } + llassert(new_joint_names.size() <= max_joints); for (U32 j = 0; j < skin->mJointNames.size(); ++j) { -- cgit v1.2.3 From 3b702b6616854d19c9432e568197dc60fc772d9c Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Mon, 26 Oct 2015 11:05:58 -0700 Subject: SL-113: use product approved message string --- indra/newview/skins/default/xui/en/notifications.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 30e7caad76..bc051ca1ad 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10263,7 +10263,7 @@ Not enough script resources available to attach object! name="IllegalAttachment" type="notify"> fail - The attachment point specified is not valid and the item has been attached to the default location: chest. + The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead. Date: Tue, 27 Oct 2015 15:15:34 -0700 Subject: Fixes SL-202 joint offset and skin weight import. Race condition still exists. --- indra/llprimitive/lldaeloader.cpp | 12 ++----- indra/llprimitive/lldaeloader.h | 1 - indra/newview/llappviewer.cpp | 2 +- indra/newview/llfloatermodelpreview.cpp | 20 ++++------- indra/newview/llfloatermodelpreview.h | 2 -- indra/newview/llvoavatar.cpp | 63 +-------------------------------- indra/newview/llvoavatar.h | 5 +-- 7 files changed, 13 insertions(+), 92 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 6db6bc4dc7..b4c5c844ef 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1303,8 +1303,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do mat.mMatrix[i][j] = transform[k*16 + i + j*4]; } } - - model->mSkinInfo.mInvBindMatrix.push_back(mat); + model->mSkinInfo.mInvBindMatrix.push_back(mat); } } } @@ -1362,20 +1361,15 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do std::string lookingForJoint = (*jointIt).c_str(); //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key //and store it in the alternate bind matrix - if ( mJointList.find( lookingForJoint ) != mJointList.end() ) + if ( mJointMap.find( lookingForJoint ) != mJointMap.end() ) { - LLMatrix4 jointTransform = mJointList[lookingForJoint]; LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); } else { - LL_WARNS()<<"Possibly misnamed/missing joint [" <mSkinInfo.mAlternateBindMatrix.push_back( emptyInverse ); + LL_WARNS()<<"Possibly misnamed/missing joint [" <getName()); } } + + std::stringstream cvstr; + for (S32 i = 0; i < av->mNumCollisionVolumes; i++) + { + legal_joint_names.push_back(av->mCollisionVolumes[i].getName()); + cvstr << legal_joint_names[i]; + } } void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm) @@ -3351,19 +3358,6 @@ void LLModelPreview::update() } } -//----------------------------------------------------------------------------- -// getTranslationForJointOffset() -//----------------------------------------------------------------------------- -LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint ) -{ - LLMatrix4 jointTransform; - if ( mJointTransformMap.find( joint ) != mJointTransformMap.end() ) - { - jointTransform = mJointTransformMap[joint]; - return jointTransform.getTranslation(); - } - return LLVector3(0.0f,0.0f,0.0f); -} //----------------------------------------------------------------------------- // createPreviewAvatar //----------------------------------------------------------------------------- diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 25c650a725..d9351029ec 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -300,8 +300,6 @@ public: void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } - LLVector3 getTranslationForJointOffset( std::string joint ); - static bool sIgnoreLoadedCallback; protected: diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 68bb39eb98..3b482e1bc0 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -213,24 +213,6 @@ struct LLTextureMaskData ** **/ -//------------------------------------------------------------------------ -// LLVOAvatarBoneInfo -// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. -//------------------------------------------------------------------------ -struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block -{ - LLVOAvatarCollisionVolumeInfo() - : name("name"), - pos("pos"), - rot("rot"), - scale("scale") - {} - - Mandatory name; - Mandatory pos, - rot, - scale; -}; struct LLAppearanceMessageContents { @@ -252,49 +234,6 @@ struct LLAppearanceMessageContents bool mHoverOffsetWasSet; }; -struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock - { - Alternative > bone; - Alternative collision_volume; - - LLVOAvatarChildJoint() - : bone("bone"), - collision_volume("collision_volume") - {} -}; - - - -struct LLVOAvatarBoneInfo : public LLInitParam::Block -{ - LLVOAvatarBoneInfo() - : pivot("pivot") - {} - - Mandatory pivot; - Multiple children; -}; - -//------------------------------------------------------------------------ -// LLVOAvatarSkeletonInfo -// Overall avatar skeleton -//------------------------------------------------------------------------ -struct LLVOAvatarSkeletonInfo : public LLInitParam::Block -{ - LLVOAvatarSkeletonInfo() - : skeleton_root(""), - num_bones("num_bones"), - num_collision_volumes("num_collision_volumes"), - version("version") - {} - - Mandatory version; - Mandatory num_bones, - num_collision_volumes; - Mandatory skeleton_root; -}; - - //----------------------------------------------------------------------------- // class LLBodyNoiseMotion @@ -1527,7 +1466,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& for (S32 i = 0; i < mNumCollisionVolumes; ++i) { mCollisionVolumes[i].updateWorldMatrix(); - + glh::matrix4f mat((F32*) mCollisionVolumes[i].getXform()->getWorldMatrix().mMatrix); glh::matrix4f inverse = mat.inverse(); glh::matrix4f norm_mat = inverse.transpose(); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5b4379165a..7a2355b447 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -68,11 +68,8 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -struct LLVOAvatarBoneInfo; -struct LLVOAvatarChildJoint; -//class LLViewerJoint; + struct LLAppearanceMessageContents; -struct LLVOAvatarSkeletonInfo; class LLViewerJointMesh; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From ded9b10d5dd60cb85934d0ab029e8c5a297d4123 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 29 Oct 2015 16:09:22 -0400 Subject: SL-114 WIP - constrain uploaded meshes based on max joints per mesh. Set max joints per mesh to 110. Also fixed some uninitialized members of LLModelLoader. --- indra/llcharacter/lljoint.h | 2 +- indra/llprimitive/lldaeloader.cpp | 4 +++- indra/llprimitive/lldaeloader.h | 1 + indra/llprimitive/llmodelloader.cpp | 17 +++++++++++++++-- indra/llprimitive/llmodelloader.h | 4 +++- indra/newview/llfloatermodelpreview.cpp | 1 + 6 files changed, 24 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 113742ad74..2a8ebed408 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -42,7 +42,7 @@ const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // BENTO JOINT COUNT LIMIT const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! -const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 132; +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; // FIXME BENTO - these should be higher than the joint_num of any // other joint, to avoid conflicts in updateMotionsByType() diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index c50db824af..c7eaba412d 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -811,6 +811,7 @@ LLDAELoader::LLDAELoader( JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, JointNameSet& legalJointNames, + U32 maxJointsPerMesh, U32 modelLimit) : LLModelLoader( filename, @@ -822,7 +823,8 @@ LLDAELoader::LLDAELoader( opaque_userdata, jointTransformMap, jointsFromNodes, - legalJointNames), + legalJointNames, + maxJointsPerMesh), mGeneratedModelLimit(modelLimit) { } diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 79856741db..ebc6acf18f 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -57,6 +57,7 @@ public: JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, JointNameSet& legalJointNames, + U32 maxJointsPerMesh, U32 modelLimit); virtual ~LLDAELoader() ; diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 9cf0f10a7e..4acf695f22 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -111,12 +111,14 @@ LLModelLoader::LLModelLoader( void* opaque_userdata, JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, - JointNameSet& legalJointNames) + JointNameSet& legalJointNames, + U32 maxJointsPerMesh) : mJointList( jointTransformMap ) , mJointsFromNode( jointsFromNodes ) , LLThread("Model Loader") , mFilename(filename) , mLod(lod) +, mTrySLM(false) , mFirstTransform(TRUE) , mNumOfFetchingTextures(0) , mLoadCallback(load_cb) @@ -124,9 +126,13 @@ LLModelLoader::LLModelLoader( , mTextureLoadFunc(texture_load_func) , mStateCallback(state_cb) , mOpaqueData(opaque_userdata) +, mRigParityWithScene(false) +, mRigValidJointUpload(false) +, mLegacyRigValid(false) , mNoNormalize(false) , mNoOptimize(false) , mCacheOnlyHitIfRigged(false) +, mMaxJointsPerMesh(maxJointsPerMesh) { // Recognize all names we've been told are legal. for (JointNameSet::iterator joint_name_it = legalJointNames.begin(); @@ -456,7 +462,14 @@ void LLModelLoader::loadModelCallback() void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ) { critiqueJointToNodeMappingFromScene(); - + + if (jointListFromAsset.size()>mMaxJointsPerMesh) + { + LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; + LL_WARNS() << "Skinning disabled" << LL_ENDL; + return; + } + //Determines the following use cases for a rig: //1. It is suitable for upload with skin weights & joint positions, or //2. It is suitable for upload as standard av with just skin weights diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index 894de2c76f..0b5d7168fa 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -117,6 +117,7 @@ public: JointMap mJointMap; JointTransformMap& mJointList; JointNameSet& mJointsFromNode; + U32 mMaxJointsPerMesh; LLModelLoader( std::string filename, @@ -128,7 +129,8 @@ public: void* opaque_userdata, JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, - JointNameSet& legalJointNames); + JointNameSet& legalJointNames, + U32 maxJointsPerMesh); virtual ~LLModelLoader() ; virtual void setNoNormalize() { mNoNormalize = true; } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 9c72238d87..a8069dd569 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1786,6 +1786,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable mJointTransformMap, mJointsFromNode, legal_joint_names, + LLSkinningUtil::getMaxJointCount(), gSavedSettings.getU32("ImporterModelLimit")); if (force_disable_slm) -- cgit v1.2.3 From 5601e4c4a10ca960aa86fb10d04937823173fc23 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 2 Nov 2015 15:31:38 -0500 Subject: SL-124 WIP - notes for pre-release cleanup. --- indra/newview/llskinningutil.cpp | 1 + indra/newview/llviewercontrol.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 5fd2248060..4f974d5912 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -113,6 +113,7 @@ U32 get_proxy_joint_index(U32 joint_index, LLVOAvatar *avatar, std::vectorgetSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); + // BENTO - remove MaxJointsPerMeshObject before release gSavedSettings.getControl("MaxJointsPerMeshObject")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2)); gSavedSettings.getControl("IncludeEnhancedSkeleton")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2)); } -- cgit v1.2.3 From 1a7b2d3d388d12a16fab5e585f06ab0574136f3d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 4 Nov 2015 09:33:43 -0500 Subject: SL-114 WIP - show skin weights checkbox can get out of sync with corresponding view option. --- indra/newview/llfloatermodelpreview.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index a8069dd569..dac49aa0b3 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3578,6 +3578,7 @@ BOOL LLModelPreview::render() fmp->enableViewOption("show_skin_weight"); fmp->setViewOptionEnabled("show_joint_positions", skin_weight); mFMP->childEnable("upload_skin"); + mFMP->childSetValue("show_skin_weight", skin_weight); } } else -- cgit v1.2.3 From 3cf938bcec9a4925a4f7d8becb9b89ff559eb2e3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 4 Nov 2015 16:41:37 -0500 Subject: SL-124 WIP - BENTO comments and related cleanup --- indra/llcharacter/llbvhloader.cpp | 3 +-- indra/llcharacter/lljoint.h | 2 +- indra/llprimitive/lldaeloader.cpp | 4 ---- indra/llprimitive/llmodel.h | 2 -- indra/newview/llskinningutil.cpp | 4 +--- 5 files changed, 3 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 4dedeeab52..b4f0bb9e18 100755 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -903,8 +903,7 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & return E_ST_NO_CHANNELS; } - // FIXME BENTO do we want to open up motion of non-hip joints or - // not? Already effectively allowed via .anim upload. + // Animating position (via mNumChannels = 6) is only supported for mPelvis. int res = sscanf(line.c_str(), " CHANNELS %d", &joint->mNumChannels); if ( res != 1 ) { diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2a8ebed408..8d380cdc82 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,7 +40,7 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; -// BENTO JOINT COUNT LIMIT +// BENTO JOINT COUNT LIMIT - need to set this to final skeleton size + 2 const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4! const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index c7eaba412d..ab38973dfe 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1259,8 +1259,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do name = mJointMap[name]; } model->mSkinInfo.mJointNames.push_back(name); - // BENTO this does not appear to be used anywhere. - // model->mSkinInfo.mJointMap[name] = j; } } else @@ -1278,8 +1276,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do name = mJointMap[name]; } model->mSkinInfo.mJointNames.push_back(name); - // BENTO not used? - // model->mSkinInfo.mJointMap[name] = j; } } } diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 56844ac16d..5f98942340 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -47,8 +47,6 @@ public: std::vector mInvBindMatrix; std::vector mAlternateBindMatrix; std::vector mJointRemap; - // BENTO not used? - //std::map mJointMap; LLMeshSkinInfo() { } LLMeshSkinInfo(LLSD& data); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 4f974d5912..c32345cbe9 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -85,9 +85,7 @@ U32 get_proxy_joint_index(U32 joint_index, LLVOAvatar *avatar, std::vectorgetJoint(joint_names[j_proxy]); llassert(joint); - // BENTO - test of simple push-to-base-ancestor - // complexity reduction scheme. Find the first - // ancestor that's not flagged as extended, or the + // Find the first ancestor that's not flagged as extended, or the // last ancestor that's rigged in this mesh, whichever // comes first. while (1) -- cgit v1.2.3 From be11d020ca6b941ec86622718c9eeafd5fddb7b5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 9 Nov 2015 14:57:00 -0500 Subject: SL-266 WIP - removed obsolete rigParityWithScene code, set legacy and joint offset upload based on AND-ing state of all meshes in file. --- indra/llprimitive/lldaeloader.cpp | 69 +++++++++++++----------- indra/llprimitive/llmodelloader.cpp | 96 ++++++++++++++------------------- indra/llprimitive/llmodelloader.h | 5 -- indra/newview/llfloatermodelpreview.cpp | 1 - indra/newview/llfloatermodelpreview.h | 3 -- 5 files changed, 77 insertions(+), 97 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index ab38973dfe..7e2cf67297 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1187,6 +1187,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do extractTranslation( pTranslateA, workingTransform ); } else + { if ( pTranslateB ) { extractTranslation( pTranslateB, workingTransform ); @@ -1211,9 +1212,10 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do } } + } - //Store the joint transform w/respect to it's name. - mJointList[(*jointIt).second.c_str()] = workingTransform; + //Store the joint transform w/respect to its name. + mJointList[(*jointIt).second.c_str()] = workingTransform; } } @@ -1319,35 +1321,40 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do if ( !missingSkeletonOrScene ) { - //Set the joint translations on the avatar - if it's a full mapping - //The joints are reset in the dtor - if ( getRigWithSceneParity() ) - { - JointMap :: const_iterator masterJointIt = mJointMap.begin(); - JointMap :: const_iterator masterJointItEnd = mJointMap.end(); - for (;masterJointIt!=masterJointItEnd;++masterJointIt ) - { - std::string lookingForJoint = (*masterJointIt).first.c_str(); - - if ( mJointList.find( lookingForJoint ) != mJointList.end() ) - { - //LL_INFOS()<<"joint "<addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); - } - else - { - //Most likely an error in the asset. - LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; - } - } - } - } + //Set the joint translations on the avatar + JointMap :: const_iterator masterJointIt = mJointMap.begin(); + JointMap :: const_iterator masterJointItEnd = mJointMap.end(); + for (;masterJointIt!=masterJointItEnd;++masterJointIt ) + { + std::string lookingForJoint = (*masterJointIt).first.c_str(); + + if ( mJointList.find( lookingForJoint ) != mJointList.end() ) + { + //LL_INFOS()<<"joint "<addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); + } + else + { + //Most likely an error in the asset. + LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; + } + } + } } //missingSkeletonOrScene //We need to construct the alternate bind matrix (which contains the new joint positions) diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 4acf695f22..b12d1042da 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -126,9 +126,8 @@ LLModelLoader::LLModelLoader( , mTextureLoadFunc(texture_load_func) , mStateCallback(state_cb) , mOpaqueData(opaque_userdata) -, mRigParityWithScene(false) -, mRigValidJointUpload(false) -, mLegacyRigValid(false) +, mRigValidJointUpload(true) +, mLegacyRigValid(true) , mNoNormalize(false) , mNoOptimize(false) , mCacheOnlyHitIfRigged(false) @@ -461,15 +460,6 @@ void LLModelLoader::loadModelCallback() //----------------------------------------------------------------------------- void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ) { - critiqueJointToNodeMappingFromScene(); - - if (jointListFromAsset.size()>mMaxJointsPerMesh) - { - LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; - LL_WARNS() << "Skinning disabled" << LL_ENDL; - return; - } - //Determines the following use cases for a rig: //1. It is suitable for upload with skin weights & joint positions, or //2. It is suitable for upload as standard av with just skin weights @@ -477,59 +467,27 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAs return false; } + // Too many joints in asset + if (jointListFromAsset.size()>mMaxJointsPerMesh) + { + LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; + LL_WARNS() << "Skinning disabled" << LL_ENDL; + return false; + } + + // Unknown joints in asset + S32 unknown_joint_count = 0; + for (std::vector::const_iterator it = jointListFromAsset.begin(); + it != jointListFromAsset.end(); ++it) + { + if (mJointMap.find(*it)==mJointMap.end()) + { + LL_WARNS() << "Rig to unrecognized name " << *it << ", isRigLegacy() will fail" << LL_ENDL; + unknown_joint_count++; + } + } + if (unknown_joint_count>0) + { + return false; + } + bool result = false; JointNameSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index 0b5d7168fa..ad8372f077 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -161,7 +161,6 @@ public: //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) void critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ); - void critiqueJointToNodeMappingFromScene( void ); //Determines if a rig is a legacy from the joint list bool isRigLegacy( const std::vector &jointListFromAsset ); @@ -169,9 +168,6 @@ public: //Determines if a rig is suitable for upload bool isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ); - void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } - const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } - const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } @@ -194,7 +190,6 @@ protected: LLModelLoader::state_callback_t mStateCallback; void* mOpaqueData; - bool mRigParityWithScene; bool mRigValidJointUpload; bool mLegacyRigValid; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index dac49aa0b3..8c3c12291e 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1184,7 +1184,6 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) , mPhysicsSearchLOD( LLModel::LOD_PHYSICS ) , mResetJoints( false ) , mModelNoErrors( true ) -, mRigParityWithScene( false ) , mLastJointUpdate( false ) { mNeedsUpdate = TRUE; diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index d9351029ec..2a39f54e92 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -297,8 +297,6 @@ public: void setLoadState( U32 state ) { mLoadState = state; } U32 getLoadState() { return mLoadState; } - void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } - const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } static bool sIgnoreLoadedCallback; @@ -346,7 +344,6 @@ private: bool mLoading; U32 mLoadState; bool mResetJoints; - bool mRigParityWithScene; bool mModelNoErrors; std::map mViewOption; -- cgit v1.2.3 From fcf2f235b763a4e1e2814685c3086da3933eac74 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 9 Nov 2015 14:58:26 -0500 Subject: SL-263 FIX - fallback code to prevent crash, won't be invoked unless there's a bug somewhere upstream. --- indra/newview/llskinningutil.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index c32345cbe9..279035d769 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -232,7 +232,18 @@ void LLSkinningUtil::initSkinningMatrixPalette( { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); + if (joint) + { + mat[j] *= joint->getWorldMatrix(); + } + else + { + // This shouldn't happen - in mesh upload, skinned + // rendering should be disabled unless all joints are + // valid. In other cases of skinned rendering, invalid + // joints should already have been removed during remap. + LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << LL_ENDL; + } } } -- cgit v1.2.3 From b72480ddb9b01202f1bbe4bfb84595549faeacf3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 10 Nov 2015 15:52:41 -0500 Subject: SL-114 WIP - made mesh upload errors/warnings slightly more informative and less spammy. --- indra/llprimitive/lldaeloader.cpp | 4 +- indra/llprimitive/llmodelloader.cpp | 74 ++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 7e2cf67297..f83f58faa6 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1376,7 +1376,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do } else { - LL_WARNS()<<"Possibly misnamed/missing joint [" <getAttribute("id") << "\"" << LL_ENDL; + LL_DEBUGS("Mesh")<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; return NULL; } diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index b12d1042da..bdecfe243b 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -475,14 +475,14 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAs if (jointListFromAsset.size()>mMaxJointsPerMesh) { LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; - LL_WARNS() << "Skinning disabled" << LL_ENDL; + LL_WARNS() << "Skinning disabled due to too many joints" << LL_ENDL; return false; } @@ -514,77 +514,65 @@ bool LLModelLoader::isRigLegacy( const std::vector &jointListFromAs { if (mJointMap.find(*it)==mJointMap.end()) { - LL_WARNS() << "Rig to unrecognized name " << *it << ", isRigLegacy() will fail" << LL_ENDL; + LL_WARNS() << "Rigged to unrecognized joint name " << *it << LL_ENDL; unknown_joint_count++; } } if (unknown_joint_count>0) { + LL_WARNS() << "Skinning disabled due to unknown joints" << LL_ENDL; return false; } - bool result = false; - + // Note that this is basically the same code as + // isRigSuitableForJointPositionUpload(), but the set of joints is + // different. JointNameSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); JointNameSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - + + S32 missing_joint_count = 0; for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } + if (std::find(modelJointIt,modelJointItEnd,*masterJointIt)==modelJointItEnd) + { + LL_INFOS() <<" Asset did not contain a joint required for skinned mesh upload: " << *masterJointIt<< LL_ENDL; + missing_joint_count++; + } } - return result; + if (missing_joint_count>0) + { + LL_WARNS() << "Skinning disabled due to missing joints" << LL_ENDL; + } + return missing_joint_count==0; } //----------------------------------------------------------------------------- // isRigSuitableForJointPositionUpload() //----------------------------------------------------------------------------- bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ) { - bool result = false; - JointNameSet :: const_iterator masterJointIt = mMasterJointList.begin(); JointNameSet :: const_iterator masterJointEndIt = mMasterJointList.end(); std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); + S32 missing_joint_count = 0; for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } + if (std::find(modelJointIt,modelJointItEnd,*masterJointIt)==modelJointItEnd) + { + LL_INFOS() <<" Asset did not contain a joint required for joint position upload: " << *masterJointIt<< LL_ENDL; + missing_joint_count++; + } } - return result; + if (missing_joint_count>0) + { + LL_WARNS() << "Joint upload disabled due to missing joints" << LL_ENDL; + } + return missing_joint_count==0; } -- cgit v1.2.3 From 146919fa764bed09bfa5e27bc30d02ce2afb6188 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Wed, 11 Nov 2015 13:44:51 -0800 Subject: animations and meshes will recognize all joint names in joint_aliases.xml --- indra/llcharacter/llbvhloader.cpp | 589 ++++----------------------- indra/llcharacter/llbvhloader.h | 11 +- indra/llprimitive/lldaeloader.cpp | 4 +- indra/llprimitive/lldaeloader.h | 1 + indra/llprimitive/llmodelloader.cpp | 71 +--- indra/llprimitive/llmodelloader.h | 3 +- indra/newview/CMakeLists.txt | 2 +- indra/newview/app_settings/anim.ini | 87 ---- indra/newview/app_settings/joint_aliases.xml | 97 +++++ indra/newview/llfloaterbvhpreview.cpp | 18 +- indra/newview/llfloaterbvhpreview.h | 3 +- indra/newview/llfloatermodelpreview.cpp | 7 + indra/newview/llstartup.cpp | 2 +- indra/newview/llvoavatar.cpp | 23 ++ indra/newview/llvoavatar.h | 3 + 15 files changed, 257 insertions(+), 664 deletions(-) delete mode 100755 indra/newview/app_settings/anim.ini create mode 100755 indra/newview/app_settings/joint_aliases.xml (limited to 'indra') diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 4dedeeab52..cc2505a5ab 100755 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -37,6 +37,7 @@ #include "llquantize.h" #include "llstl.h" #include "llapr.h" +#include "llsdserialize.h" using namespace std; @@ -122,47 +123,21 @@ LLQuaternion::Order bvhStringToOrder( char *str ) // LLBVHLoader() //----------------------------------------------------------------------------- -/* - LLBVHLoader::LLBVHLoader(const char* buffer) +LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::deque& legal_joint_names) { reset(); + errorLine = 0; + + // Recognize all names we've been told are legal. + for (std::deque::iterator joint_name_it = legal_joint_names.begin(); + joint_name_it != legal_joint_names.end(); ++joint_name_it) + { + const std::string& name = *joint_name_it; - mStatus = loadTranslationTable("anim.ini"); - - if (mStatus == LLBVHLoader::ST_NO_XLT_FILE) - { - LL_WARNS() << "NOTE: No translation table found." << LL_ENDL; - return; - } - else - { - if (mStatus != LLBVHLoader::ST_OK) - { - LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; - return; - } - } - - char error_text[128]; // Flawfinder: ignore - S32 error_line; - mStatus = loadBVHFile(buffer, error_text, error_line); - if (mStatus != LLBVHLoader::ST_OK) - { - LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; - return; - } - - applyTranslations(); - optimize(); + makeTranslation(name, name); + } - mInitialized = TRUE; -} -*/ -LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine) -{ - reset(); - errorLine = 0; - mStatus = loadTranslationTable("anim.ini"); + mStatus = loadAliases("joint_aliases.xml"); //Load joint name aliases loadStatus = mStatus; LL_INFOS("BVH") << "Load Status 00 : " << loadStatus << LL_ENDL; if (mStatus == E_ST_NO_XLT_FILE) @@ -184,7 +159,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error char error_text[128]; /* Flawfinder: ignore */ S32 error_line; - mStatus = loadBVHFile(buffer, error_text, error_line); + mStatus = loadBVHFile(buffer, error_text, error_line); //Reads all joints in BVH file. LL_DEBUGS("BVH") << "============================================================" << LL_ENDL; LL_DEBUGS("BVH") << "Raw data from file" << LL_ENDL; @@ -198,7 +173,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error return; } - applyTranslations(); + applyTranslations(); //Maps between joints found in file and the aliased names. optimize(); LL_DEBUGS("BVH") << "============================================================" << LL_ENDL; @@ -215,464 +190,64 @@ LLBVHLoader::~LLBVHLoader() mJoints.clear(); } -//------------------------------------------------------------------------ -// LLBVHLoader::loadTranslationTable() -//------------------------------------------------------------------------ -ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) +void LLBVHLoader::makeTranslation(std::string alias_name, std::string joint_name) { - mLineNumber = 0; - mTranslations.clear(); - mConstraints.clear(); - - //-------------------------------------------------------------------- - // open file - //-------------------------------------------------------------------- - std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); - - LLAPRFile infile ; - infile.open(path, LL_APR_R); - apr_file_t *fp = infile.getFileHandle(); - if (!fp) - return E_ST_NO_XLT_FILE; - - LL_INFOS("BVH") << "NOTE: Loading translation table: " << fileName << LL_ENDL; - - //-------------------------------------------------------------------- - // register file to be closed on function exit - //-------------------------------------------------------------------- - - //-------------------------------------------------------------------- - // load header - //-------------------------------------------------------------------- - if ( ! getLine(fp) ) - return E_ST_EOF; - if ( strncmp(mLine, "Translations 1.0", 16) ) - return E_ST_NO_XLT_HEADER; - - //-------------------------------------------------------------------- - // load data one line at a time - //-------------------------------------------------------------------- - BOOL loadingGlobals = FALSE; - Translation *trans = NULL; - while ( getLine(fp) ) - { - //---------------------------------------------------------------- - // check the 1st token on the line to determine if it's empty or a comment - //---------------------------------------------------------------- - char token[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %127s", token) != 1 ) /* Flawfinder: ignore */ - continue; - - if (token[0] == '#') - continue; - - //---------------------------------------------------------------- - // check if a [jointName] or [GLOBALS] was specified. - //---------------------------------------------------------------- - if (token[0] == '[') - { - char name[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " [%127[^]]", name) != 1 ) - return E_ST_NO_XLT_NAME; - - if (strcmp(name, "GLOBALS")==0) - { - loadingGlobals = TRUE; - continue; - } - else - { - loadingGlobals = FALSE; - Translation &newTrans = mTranslations[ name ]; - trans = &newTrans; - continue; - } - } - - //---------------------------------------------------------------- - // check for optional emote - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "emote")==0) - { - char emote_str[1024]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_EMOTE; - - mEmoteName.assign( emote_str ); -// LL_INFOS() << "NOTE: Emote: " << mEmoteName.c_str() << LL_ENDL; - continue; - } - - - //---------------------------------------------------------------- - // check for global priority setting - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "priority")==0) - { - S32 priority; - if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return E_ST_NO_XLT_PRIORITY; - - mPriority = priority; -// LL_INFOS() << "NOTE: Priority: " << mPriority << LL_ENDL; - continue; - } - - //---------------------------------------------------------------- - // check for global loop setting - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "loop")==0) - { - char trueFalse[128]; /* Flawfinder: ignore */ - trueFalse[0] = '\0'; - - F32 loop_in = 0.f; - F32 loop_out = 1.f; - - if ( sscanf(mLine, " %*s = %f %f", &loop_in, &loop_out) == 2 ) - { - mLoop = TRUE; - } - else if ( sscanf(mLine, " %*s = %127s", trueFalse) == 1 ) /* Flawfinder: ignore */ - { - mLoop = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); - } - else - { - return E_ST_NO_XLT_LOOP; - } - - mLoopInPoint = loop_in * mDuration; - mLoopOutPoint = loop_out * mDuration; - - continue; - } - - //---------------------------------------------------------------- - // check for global easeIn setting - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easein")==0) - { - F32 duration; - char type[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_EASEIN; - - mEaseIn = duration; - continue; - } - - //---------------------------------------------------------------- - // check for global easeOut setting - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easeout")==0) - { - F32 duration; - char type[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_EASEOUT; - - mEaseOut = duration; - continue; - } - - //---------------------------------------------------------------- - // check for global handMorph setting - //---------------------------------------------------------------- - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "hand")==0) - { - S32 handMorph; - if (sscanf(mLine, " %*s = %d", &handMorph) != 1) - return E_ST_NO_XLT_HAND; - - mHand = handMorph; - continue; - } - - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "constraint")==0) - { - Constraint constraint; - - // try reading optional target direction - if(sscanf( /* Flawfinder: ignore */ - mLine, - " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", - &constraint.mChainLength, - &constraint.mEaseInStart, - &constraint.mEaseInStop, - &constraint.mEaseOutStart, - &constraint.mEaseOutStop, - constraint.mSourceJointName, - &constraint.mSourceOffset.mV[VX], - &constraint.mSourceOffset.mV[VY], - &constraint.mSourceOffset.mV[VZ], - constraint.mTargetJointName, - &constraint.mTargetOffset.mV[VX], - &constraint.mTargetOffset.mV[VY], - &constraint.mTargetOffset.mV[VZ], - &constraint.mTargetDir.mV[VX], - &constraint.mTargetDir.mV[VY], - &constraint.mTargetDir.mV[VZ]) != 16) - { - if(sscanf( /* Flawfinder: ignore */ - mLine, - " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", - &constraint.mChainLength, - &constraint.mEaseInStart, - &constraint.mEaseInStop, - &constraint.mEaseOutStart, - &constraint.mEaseOutStop, - constraint.mSourceJointName, - &constraint.mSourceOffset.mV[VX], - &constraint.mSourceOffset.mV[VY], - &constraint.mSourceOffset.mV[VZ], - constraint.mTargetJointName, - &constraint.mTargetOffset.mV[VX], - &constraint.mTargetOffset.mV[VY], - &constraint.mTargetOffset.mV[VZ]) != 13) - { - return E_ST_NO_CONSTRAINT; - } - } - else - { - // normalize direction - if (!constraint.mTargetDir.isExactlyZero()) - { - constraint.mTargetDir.normVec(); - } - - } - - constraint.mConstraintType = CONSTRAINT_TYPE_POINT; - mConstraints.push_back(constraint); - continue; - } - - if (loadingGlobals && LLStringUtil::compareInsensitive(token, "planar_constraint")==0) - { - Constraint constraint; - - // try reading optional target direction - if(sscanf( /* Flawfinder: ignore */ - mLine, - " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", - &constraint.mChainLength, - &constraint.mEaseInStart, - &constraint.mEaseInStop, - &constraint.mEaseOutStart, - &constraint.mEaseOutStop, - constraint.mSourceJointName, - &constraint.mSourceOffset.mV[VX], - &constraint.mSourceOffset.mV[VY], - &constraint.mSourceOffset.mV[VZ], - constraint.mTargetJointName, - &constraint.mTargetOffset.mV[VX], - &constraint.mTargetOffset.mV[VY], - &constraint.mTargetOffset.mV[VZ], - &constraint.mTargetDir.mV[VX], - &constraint.mTargetDir.mV[VY], - &constraint.mTargetDir.mV[VZ]) != 16) - { - if(sscanf( /* Flawfinder: ignore */ - mLine, - " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", - &constraint.mChainLength, - &constraint.mEaseInStart, - &constraint.mEaseInStop, - &constraint.mEaseOutStart, - &constraint.mEaseOutStop, - constraint.mSourceJointName, - &constraint.mSourceOffset.mV[VX], - &constraint.mSourceOffset.mV[VY], - &constraint.mSourceOffset.mV[VZ], - constraint.mTargetJointName, - &constraint.mTargetOffset.mV[VX], - &constraint.mTargetOffset.mV[VY], - &constraint.mTargetOffset.mV[VZ]) != 13) - { - return E_ST_NO_CONSTRAINT; - } - } - else - { - // normalize direction - if (!constraint.mTargetDir.isExactlyZero()) - { - constraint.mTargetDir.normVec(); - } - - } - - constraint.mConstraintType = CONSTRAINT_TYPE_PLANE; - mConstraints.push_back(constraint); - continue; - } - - - //---------------------------------------------------------------- - // at this point there must be a valid trans pointer - //---------------------------------------------------------------- - if ( ! trans ) - return E_ST_NO_XLT_NAME; - - //---------------------------------------------------------------- - // check for ignore flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "ignore")==0 ) - { - char trueFalse[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_IGNORE; - - trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); - continue; - } - - //---------------------------------------------------------------- - // check for relativepos flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "relativepos")==0 ) - { - F32 x, y, z; - char relpos[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %f %f %f", &x, &y, &z) == 3 ) - { - trans->mRelativePosition.setVec( x, y, z ); - } - else if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */ - { - if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 ) - { - trans->mRelativePositionKey = TRUE; - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - - continue; - } + //Translation &newTrans = (foomap.insert(value_type(alias_name, Translation()))).first(); + Translation &newTrans = mTranslations[ alias_name ]; //Uses []'s implicit call to ctor. + + newTrans.mOutName = joint_name; + LLMatrix3 fm; + LLVector3 vect1(0, 1, 0); + LLVector3 vect2(0, 0, 1); + LLVector3 vect3(1, 0, 0); + fm.setRows(vect1, vect2, vect3); + + newTrans.mFrameMatrix = fm; + + if (joint_name == "mPelvis") + { + newTrans.mRelativePositionKey = TRUE; + newTrans.mRelativeRotationKey = TRUE; + } - //---------------------------------------------------------------- - // check for relativerot flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "relativerot")==0 ) - { - //F32 x, y, z; - char relpos[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */ - { - if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 ) - { - trans->mRelativeRotationKey = TRUE; - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - - continue; - } - - //---------------------------------------------------------------- - // check for outname value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "outname")==0 ) - { - char outName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_OUTNAME; - - trans->mOutName = outName; - continue; - } - - //---------------------------------------------------------------- - // check for frame matrix value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "frame")==0 ) - { - LLMatrix3 fm; - if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f", - &fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2], - &fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2], - &fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 ) - return E_ST_NO_XLT_MATRIX; - - trans->mFrameMatrix = fm; - continue; - } - - //---------------------------------------------------------------- - // check for offset matrix value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "offset")==0 ) - { - LLMatrix3 om; - if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f", - &om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2], - &om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2], - &om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 ) - return E_ST_NO_XLT_MATRIX; - - trans->mOffsetMatrix = om; - continue; - } - - //---------------------------------------------------------------- - // check for mergeparent value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "mergeparent")==0 ) - { - char mergeParentName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_MERGEPARENT; - - trans->mMergeParentName = mergeParentName; - continue; - } - - //---------------------------------------------------------------- - // check for mergechild value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "mergechild")==0 ) - { - char mergeChildName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_MERGECHILD; - - trans->mMergeChildName = mergeChildName; - continue; - } - - //---------------------------------------------------------------- - // check for per-joint priority - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "priority")==0 ) - { - S32 priority; - if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return E_ST_NO_XLT_PRIORITY; - - trans->mPriorityModifier = priority; - continue; - } - - } +} - infile.close() ; - return E_ST_OK; +ELoadStatus LLBVHLoader::loadAliases(const char * filename) +{ + LLSD aliases_sd; + + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,filename); + + llifstream input_stream; + input_stream.open(fullpath.c_str(), std::ios::in | std::ios::binary); + + if(input_stream.is_open()) + { + if ( LLSDSerialize::fromXML(aliases_sd, input_stream) ) + { + for(LLSD::map_iterator alias_iter = aliases_sd.beginMap(); + alias_iter != aliases_sd.endMap(); + ++alias_iter) + { + LLSD::String alias_name = alias_iter->first; + LLSD::String joint_name = alias_iter->second; + makeTranslation(alias_name, joint_name); + + } + } + else + { + return E_ST_NO_XLT_HEADER; + } + input_stream.close(); + } + else + { + LL_WARNS("BVH") << "Can't open joint alias file " << fullpath << LL_ENDL; + return E_ST_NO_XLT_FILE; + } + + return E_ST_OK; } void LLBVHLoader::dumpBVHInfo() @@ -1374,6 +949,7 @@ void LLBVHLoader::reset() mInitialized = FALSE; mEmoteName = ""; + mTranslations.clear(); } //------------------------------------------------------------------------ @@ -1603,28 +1179,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) } } - S32 num_constraints = (S32)mConstraints.size(); - dp.packS32(num_constraints, "num_constraints"); - - for (ConstraintVector::iterator constraint_it = mConstraints.begin(); - constraint_it != mConstraints.end(); - constraint_it++) - { - U8 byte = constraint_it->mChainLength; - dp.packU8(byte, "chain_length"); - - byte = constraint_it->mConstraintType; - dp.packU8(byte, "constraint_type"); - dp.packBinaryDataFixed((U8*)constraint_it->mSourceJointName, 16, "source_volume"); - dp.packVector3(constraint_it->mSourceOffset, "source_offset"); - dp.packBinaryDataFixed((U8*)constraint_it->mTargetJointName, 16, "target_volume"); - dp.packVector3(constraint_it->mTargetOffset, "target_offset"); - dp.packVector3(constraint_it->mTargetDir, "target_dir"); - dp.packF32(constraint_it->mEaseInStart, "ease_in_start"); - dp.packF32(constraint_it->mEaseInStop, "ease_in_stop"); - dp.packF32(constraint_it->mEaseOutStart, "ease_out_start"); - dp.packF32(constraint_it->mEaseOutStop, "ease_out_stop"); - } - + dp.packS32(0, "num_constraints"); + return TRUE; } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 033d8714a9..a0207750ed 100755 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -32,6 +32,7 @@ #include "llmath.h" #include "llapr.h" #include "llbvhconsts.h" +#include const S32 BVH_PARSER_LINE_SIZE = 2048; class LLDataPacker; @@ -228,7 +229,8 @@ class LLBVHLoader public: // Constructor // LLBVHLoader(const char* buffer); - LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); + LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); + LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::deque& legal_joint_names); ~LLBVHLoader(); /* @@ -267,9 +269,16 @@ public: static const char *ST_NO_XLT_EMOTE; static const char *ST_BAD_ROOT; */ + // Loads the specified translation table. ELoadStatus loadTranslationTable(const char *fileName); + //Create a new joint alias + void makeTranslation(std::string key, std::string value); + + // Loads joint aliases from XML file. + ELoadStatus loadAliases(const char * filename); + // Load the specified BVH file. // Returns status code. ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line); diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index c50db824af..63457512ff 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -811,6 +811,7 @@ LLDAELoader::LLDAELoader( JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, JointNameSet& legalJointNames, + std::string jointAliasesFilename, U32 modelLimit) : LLModelLoader( filename, @@ -822,7 +823,8 @@ LLDAELoader::LLDAELoader( opaque_userdata, jointTransformMap, jointsFromNodes, - legalJointNames), + legalJointNames, + jointAliasesFilename), mGeneratedModelLimit(modelLimit) { } diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 79856741db..52ad9d4705 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -57,6 +57,7 @@ public: JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, JointNameSet& legalJointNames, + std::string jointAliasesFilename, U32 modelLimit); virtual ~LLDAELoader() ; diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 9cf0f10a7e..b4bd467c64 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -111,7 +111,8 @@ LLModelLoader::LLModelLoader( void* opaque_userdata, JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, - JointNameSet& legalJointNames) + JointNameSet& legalJointNames, + std::string jointAliasFilename) : mJointList( jointTransformMap ) , mJointsFromNode( jointsFromNodes ) , LLThread("Model Loader") @@ -135,57 +136,27 @@ LLModelLoader::LLModelLoader( const std::string& name = *joint_name_it; mJointMap[name] = name; } + // Also support various legacy aliases for commonly used joints - mJointMap["avatar_mPelvis"] = "mPelvis"; - mJointMap["avatar_mTorso"] = "mTorso"; - mJointMap["avatar_mChest"] = "mChest"; - mJointMap["avatar_mNeck"] = "mNeck"; - mJointMap["avatar_mHead"] = "mHead"; - mJointMap["avatar_mSkull"] = "mSkull"; - mJointMap["avatar_mEyeRight"] = "mEyeRight"; - mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; - mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; - mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; - mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; - mJointMap["avatar_mWristLeft"] = "mWristLeft"; - mJointMap["avatar_mCollarRight"] = "mCollarRight"; - mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; - mJointMap["avatar_mElbowRight"] = "mElbowRight"; - mJointMap["avatar_mWristRight"] = "mWristRight"; - mJointMap["avatar_mHipRight"] = "mHipRight"; - mJointMap["avatar_mKneeRight"] = "mKneeRight"; - mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; - mJointMap["avatar_mFootRight"] = "mFootRight"; - mJointMap["avatar_mToeRight"] = "mToeRight"; - mJointMap["avatar_mHipLeft"] = "mHipLeft"; - mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; - mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; - mJointMap["avatar_mFootLeft"] = "mFootLeft"; - mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - - mJointMap["hip"] = "mPelvis"; - mJointMap["abdomen"] = "mTorso"; - mJointMap["chest"] = "mChest"; - mJointMap["neck"] = "mNeck"; - mJointMap["head"] = "mHead"; - mJointMap["figureHair"] = "mSkull"; - mJointMap["lCollar"] = "mCollarLeft"; - mJointMap["lShldr"] = "mShoulderLeft"; - mJointMap["lForeArm"] = "mElbowLeft"; - mJointMap["lHand"] = "mWristLeft"; - mJointMap["rCollar"] = "mCollarRight"; - mJointMap["rShldr"] = "mShoulderRight"; - mJointMap["rForeArm"] = "mElbowRight"; - mJointMap["rHand"] = "mWristRight"; - mJointMap["rThigh"] = "mHipRight"; - mJointMap["rShin"] = "mKneeRight"; - mJointMap["rFoot"] = "mFootRight"; - mJointMap["lThigh"] = "mHipLeft"; - mJointMap["lShin"] = "mKneeLeft"; - mJointMap["lFoot"] = "mFootLeft"; - + LLSD aliases_sd; + llifstream input_stream; + input_stream.open(jointAliasFilename.c_str(), std::ios::in | std::ios::binary); + + if(input_stream.is_open()) + { + LLSDSerialize::fromXML(aliases_sd, input_stream); + for(LLSD::map_iterator alias_iter = aliases_sd.beginMap(); + alias_iter != aliases_sd.endMap(); + ++alias_iter) + { + LLSD::String alias_name = alias_iter->first; + LLSD::String joint_name = alias_iter->second; + mJointMap[ alias_name ] = joint_name; + } + input_stream.close(); + } + //move into joint mapper class //1. joints for joint offset verification mMasterJointList.push_front("mPelvis"); diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index 894de2c76f..20c3aee649 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -128,7 +128,8 @@ public: void* opaque_userdata, JointTransformMap& jointTransformMap, JointNameSet& jointsFromNodes, - JointNameSet& legalJointNames); + JointNameSet& legalJointNames, + std::string jointAliasFilename); virtual ~LLModelLoader() ; virtual void setNoNormalize() { mNoNormalize = true; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index a006611a45..b371939fb5 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1600,12 +1600,12 @@ set_source_files_properties(${viewer_XUI_FILES} list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES}) set(viewer_APPSETTINGS_FILES - app_settings/anim.ini app_settings/cmd_line.xml app_settings/commands.xml app_settings/grass.xml app_settings/high_graphics.xml app_settings/ignorable_dialogs.xml + app_settings/joint_aliases.xml app_settings/keys.xml app_settings/keywords_lsl_default.xml app_settings/logcontrol.xml diff --git a/indra/newview/app_settings/anim.ini b/indra/newview/app_settings/anim.ini deleted file mode 100755 index 63c84e544d..0000000000 --- a/indra/newview/app_settings/anim.ini +++ /dev/null @@ -1,87 +0,0 @@ -Translations 1.0 - -[hip] - relativepos = firstkey - relativerot = firstkey - outname = mPelvis - frame = 0 1 0, 0 0 1, 1 0 0 - -[abdomen] - outname = mTorso - frame = 0 1 0, 0 0 1, 1 0 0 - -[chest] - outname = mChest - frame = 0 1 0, 0 0 1, 1 0 0 - -[neckDummy] - ignore = true - frame = 0 1 0, 0 0 1, 1 0 0 - -[neck] - outname = mNeck - frame = 0 1 0, 0 0 1, 1 0 0 - -[head] - outname = mHead - frame = 0 1 0, 0 0 1, 1 0 0 - -[figureHair] - ignore = true - frame = 0 1 0, 0 0 1, 1 0 0 - -[lCollar] - outname = mCollarLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[lShldr] - outname = mShoulderLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[lForeArm] - outname = mElbowLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[lHand] - outname = mWristLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[rCollar] - outname = mCollarRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[rShldr] - outname = mShoulderRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[rForeArm] - outname = mElbowRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[rHand] - outname = mWristRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[lThigh] - outname = mHipLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[lShin] - outname = mKneeLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[lFoot] - outname = mAnkleLeft - frame = 0 1 0, 0 0 1, 1 0 0 - -[rThigh] - outname = mHipRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[rShin] - outname = mKneeRight - frame = 0 1 0, 0 0 1, 1 0 0 - -[rFoot] - outname = mAnkleRight - frame = 0 1 0, 0 0 1, 1 0 0 \ No newline at end of file diff --git a/indra/newview/app_settings/joint_aliases.xml b/indra/newview/app_settings/joint_aliases.xml new file mode 100755 index 0000000000..1e4a233837 --- /dev/null +++ b/indra/newview/app_settings/joint_aliases.xml @@ -0,0 +1,97 @@ + + + + avatar_mPelvis + mPelvis + avatar_mTorso + mTorso + avatar_mChest + mChest + avatar_mNeck + mNeck + avatar_mHead + mHead + avatar_mSkull + mSkull + avatar_mEyeRight + mEyeRight + avatar_mEyeLeft + mEyeLeft + avatar_mCollarLeft + mCollarLeft + avatar_mShoulderLeft + mShoulderLeft + avatar_mElbowLeft + mElbowLeft + avatar_mWristLeft + mWristLeft + avatar_mCollarRight + mCollarRight + avatar_mShoulderRight + mShoulderRight + avatar_mElbowRight + mElbowRight + avatar_mWristRight + mWristRight + avatar_mHipRight + mHipRight + avatar_mKneeRight + mKneeRight + avatar_mAnkleRight + mAnkleRight + avatar_mFootRight + mFootRight + avatar_mToeRight + mToeRight + avatar_mHipLeft + mHipLeft + avatar_mKneeLeft + mKneeLeft + avatar_mAnkleLeft + mAnkleLeft + avatar_mFootLeft + mFootLeft + avatar_mToeLeft + mToeLeft + hip + mPelvis + abdomen + mTorso + chest + mChest + neck + mNeck + head + mHead + figureHair + mSkull + lCollar + mCollarLeft + lShldr + mShoulderLeft + lForeArm + mElbowLeft + lHand + mWristLeft + rCollar + mCollarRight + rShldr + mShoulderRight + rForeArm + mElbowRight + rHand + mWristRight + rThigh + mHipRight + rShin + mKneeRight + rFoot + mFootRight + lThigh + mHipLeft + lShin + mKneeLeft + lFoot + mFootLeft + + diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index a800a3ca14..97769838e8 100755 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -178,6 +178,14 @@ void LLFloaterBvhPreview::setAnimCallbacks() getChild("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1)); } +void LLFloaterBvhPreview::getLegalJointNames(std::deque& legal_joint_names) +{ + // Get all standard skeleton joints from the preview avatar. + LLPointer av = (LLVOAvatar*)mAnimPreview->getDummyAvatar(); + av->getLegalJointNames(legal_joint_names, false); +} + + //----------------------------------------------------------------------------- // postBuild() //----------------------------------------------------------------------------- @@ -215,6 +223,8 @@ BOOL LLFloaterBvhPreview::postBuild() getChildView("bad_animation_text")->setVisible(FALSE); + mAnimPreview = new LLPreviewAnimation(256, 256); + std::string exten = gDirUtilp->getExtension(mFilename); if (exten == "bvh") { @@ -241,8 +251,10 @@ BOOL LLFloaterBvhPreview::postBuild() file_buffer[file_size] = '\0'; LL_INFOS() << "Loading BVH file " << mFilename << LL_ENDL; ELoadStatus load_status = E_ST_OK; - S32 line_number = 0; - loaderp = new LLBVHLoader(file_buffer, load_status, line_number); + S32 line_number = 0; + std::deque legal_joint_names; + getLegalJointNames(legal_joint_names); + loaderp = new LLBVHLoader(file_buffer, load_status, line_number, legal_joint_names); std::string status = getString(STATUS[load_status]); if(load_status == E_ST_NO_XLT_FILE) @@ -266,8 +278,6 @@ BOOL LLFloaterBvhPreview::postBuild() mTransactionID.generate(); mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - mAnimPreview = new LLPreviewAnimation(256, 256); - // motion will be returned, but it will be in a load-pending state, as this is a new motion // this motion will not request an asset transfer until next update, so we have a chance to // load the keyframe data locally diff --git a/indra/newview/llfloaterbvhpreview.h b/indra/newview/llfloaterbvhpreview.h index b81cc6e3a5..74d77d0004 100755 --- a/indra/newview/llfloaterbvhpreview.h +++ b/indra/newview/llfloaterbvhpreview.h @@ -109,7 +109,8 @@ public: S32 status, LLExtStat ext_status); private: void setAnimCallbacks() ; - + void getLegalJointNames(std::deque& legal_joint_names); + protected: void draw(); void resetMotion(); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 9c72238d87..30051a79f1 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1712,6 +1712,8 @@ void LLModelPreview::getLegalJointNames(JointNameSet& legal_joint_names) { // Get all standard skeleton joints from the preview avatar. LLVOAvatar *av = getPreviewAvatar(); + + av->getLegalJointNames(legal_joint_names, true); const LLVOAvatar::avatar_joint_list_t &skel = av->getSkeleton(); for (S32 i=0; igetExpandedFilename(LL_PATH_APP_SETTINGS,"joint_aliases.xml"); + + mModelLoader = new LLDAELoader( filename, lod, @@ -1786,6 +1792,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable mJointTransformMap, mJointsFromNode, legal_joint_names, + joint_aliases_filename, gSavedSettings.getU32("ImporterModelLimit")); if (force_disable_slm) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 54ecc76867..6610330a56 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1258,7 +1258,7 @@ bool idle_startup() LLPostProcess::initClass(); display_startup(); - LLAvatarAppearance::initClass(gSavedSettings.getString("AvatarFileName"),gSavedSettings.getString("SkeletonFileName")); + LLAvatarAppearance::initClass(gSavedSettings.getString("AvatarFileName"),gSavedSettings.getString("SkeletonFileName")); display_startup(); LLViewerObject::initVOClasses(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3b482e1bc0..d14ec7e55b 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -937,6 +937,29 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status) return "unknown"; } +void LLVOAvatar::getLegalJointNames(std::deque& legal_joint_names, + bool include_collision_volumes) +{ + // Get all standard skeleton joints from the preview avatar. + const LLVOAvatar::avatar_joint_list_t &skel = getSkeleton(); + for (S32 i=0; igetName()); + } + } + + if (include_collision_volumes) + { + for (S32 i = 0; i < mNumCollisionVolumes; i++) + { + legal_joint_names.push_back(mCollisionVolumes[i].getName()); + } + } +} + // static void LLVOAvatar::dumpBakedStatus() { diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 7a2355b447..29f70fca18 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -72,6 +72,7 @@ class LLTexGlobalColor; struct LLAppearanceMessageContents; class LLViewerJointMesh; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar // @@ -146,6 +147,8 @@ public: void collectBakedTextureUUIDs(std::set& ids) const; void collectTextureUUIDs(std::set& ids); void releaseOldTextures(); + void getLegalJointNames(std::deque& legal_joint_names, + bool include_collision_volumes); /*virtual*/ void updateTextures(); LLViewerFetchedTexture* getBakedTextureImage(const U8 te, const LLUUID& uuid); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. -- cgit v1.2.3 From cdb96f8044fd609f92b9009450454e356008ca1c Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Fri, 13 Nov 2015 14:31:21 -0800 Subject: Post review changes. --- indra/llcharacter/llbvhloader.cpp | 333 +++++++++++++++++++++++++++- indra/llcharacter/llbvhloader.h | 3 - indra/newview/CMakeLists.txt | 1 + indra/newview/app_settings/anim.ini | 2 + indra/newview/character/avatar_skeleton.xml | 40 ++-- indra/newview/llvoavatar.cpp | 21 -- indra/newview/llvoavatar.h | 2 - 7 files changed, 354 insertions(+), 48 deletions(-) create mode 100755 indra/newview/app_settings/anim.ini (limited to 'indra') diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index a3c95fa8c9..d08788e2d1 100755 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -127,6 +127,25 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error { reset(); errorLine = 0; + mStatus = loadTranslationTable("anim.ini"); + loadStatus = mStatus; + LL_INFOS("BVH") << "Load Status 00 : " << loadStatus << LL_ENDL; + if (mStatus == E_ST_NO_XLT_FILE) + { + LL_WARNS("BVH") << "NOTE: No translation table found." << LL_ENDL; + loadStatus = mStatus; + return; + } + else + { + if (mStatus != E_ST_OK) + { + LL_WARNS("BVH") << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; + errorLine = getLineNumber(); + loadStatus = mStatus; + return; + } + } // Recognize all names we've been told are legal. std::map::iterator iter; @@ -168,6 +187,292 @@ LLBVHLoader::~LLBVHLoader() mJoints.clear(); } +//------------------------------------------------------------------------ +// LLBVHLoader::loadTranslationTable() +//------------------------------------------------------------------------ +ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) +{ + //-------------------------------------------------------------------- + // open file + //-------------------------------------------------------------------- + std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); + + LLAPRFile infile ; + infile.open(path, LL_APR_R); + apr_file_t *fp = infile.getFileHandle(); + if (!fp) + return E_ST_NO_XLT_FILE; + + LL_INFOS("BVH") << "NOTE: Loading translation table: " << fileName << LL_ENDL; + + //-------------------------------------------------------------------- + // register file to be closed on function exit + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + // load header + //-------------------------------------------------------------------- + if ( ! getLine(fp) ) + return E_ST_EOF; + if ( strncmp(mLine, "Translations 1.0", 16) ) + return E_ST_NO_XLT_HEADER; + + //-------------------------------------------------------------------- + // load data one line at a time + //-------------------------------------------------------------------- + BOOL loadingGlobals = FALSE; + while ( getLine(fp) ) + { + //---------------------------------------------------------------- + // check the 1st token on the line to determine if it's empty or a comment + //---------------------------------------------------------------- + char token[128]; /* Flawfinder: ignore */ + if ( sscanf(mLine, " %127s", token) != 1 ) /* Flawfinder: ignore */ + continue; + + if (token[0] == '#') + continue; + + //---------------------------------------------------------------- + // check if a [jointName] or [GLOBALS] was specified. + //---------------------------------------------------------------- + if (token[0] == '[') + { + char name[128]; /* Flawfinder: ignore */ + if ( sscanf(mLine, " [%127[^]]", name) != 1 ) + return E_ST_NO_XLT_NAME; + + if (strcmp(name, "GLOBALS")==0) + { + loadingGlobals = TRUE; + continue; + } + } + + //---------------------------------------------------------------- + // check for optional emote + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "emote")==0) + { + char emote_str[1024]; /* Flawfinder: ignore */ + if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */ + return E_ST_NO_XLT_EMOTE; + + mEmoteName.assign( emote_str ); +// LL_INFOS() << "NOTE: Emote: " << mEmoteName.c_str() << LL_ENDL; + continue; + } + + + //---------------------------------------------------------------- + // check for global priority setting + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "priority")==0) + { + S32 priority; + if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) + return E_ST_NO_XLT_PRIORITY; + + mPriority = priority; +// LL_INFOS() << "NOTE: Priority: " << mPriority << LL_ENDL; + continue; + } + + //---------------------------------------------------------------- + // check for global loop setting + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "loop")==0) + { + char trueFalse[128]; /* Flawfinder: ignore */ + trueFalse[0] = '\0'; + + F32 loop_in = 0.f; + F32 loop_out = 1.f; + + if ( sscanf(mLine, " %*s = %f %f", &loop_in, &loop_out) == 2 ) + { + mLoop = TRUE; + } + else if ( sscanf(mLine, " %*s = %127s", trueFalse) == 1 ) /* Flawfinder: ignore */ + { + mLoop = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); + } + else + { + return E_ST_NO_XLT_LOOP; + } + + mLoopInPoint = loop_in * mDuration; + mLoopOutPoint = loop_out * mDuration; + + continue; + } + + //---------------------------------------------------------------- + // check for global easeIn setting + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easein")==0) + { + F32 duration; + char type[128]; /* Flawfinder: ignore */ + if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ + return E_ST_NO_XLT_EASEIN; + + mEaseIn = duration; + continue; + } + + //---------------------------------------------------------------- + // check for global easeOut setting + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easeout")==0) + { + F32 duration; + char type[128]; /* Flawfinder: ignore */ + if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ + return E_ST_NO_XLT_EASEOUT; + + mEaseOut = duration; + continue; + } + + //---------------------------------------------------------------- + // check for global handMorph setting + //---------------------------------------------------------------- + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "hand")==0) + { + S32 handMorph; + if (sscanf(mLine, " %*s = %d", &handMorph) != 1) + return E_ST_NO_XLT_HAND; + + mHand = handMorph; + continue; + } + + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "constraint")==0) + { + Constraint constraint; + + // try reading optional target direction + if(sscanf( /* Flawfinder: ignore */ + mLine, + " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", + &constraint.mChainLength, + &constraint.mEaseInStart, + &constraint.mEaseInStop, + &constraint.mEaseOutStart, + &constraint.mEaseOutStop, + constraint.mSourceJointName, + &constraint.mSourceOffset.mV[VX], + &constraint.mSourceOffset.mV[VY], + &constraint.mSourceOffset.mV[VZ], + constraint.mTargetJointName, + &constraint.mTargetOffset.mV[VX], + &constraint.mTargetOffset.mV[VY], + &constraint.mTargetOffset.mV[VZ], + &constraint.mTargetDir.mV[VX], + &constraint.mTargetDir.mV[VY], + &constraint.mTargetDir.mV[VZ]) != 16) + { + if(sscanf( /* Flawfinder: ignore */ + mLine, + " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", + &constraint.mChainLength, + &constraint.mEaseInStart, + &constraint.mEaseInStop, + &constraint.mEaseOutStart, + &constraint.mEaseOutStop, + constraint.mSourceJointName, + &constraint.mSourceOffset.mV[VX], + &constraint.mSourceOffset.mV[VY], + &constraint.mSourceOffset.mV[VZ], + constraint.mTargetJointName, + &constraint.mTargetOffset.mV[VX], + &constraint.mTargetOffset.mV[VY], + &constraint.mTargetOffset.mV[VZ]) != 13) + { + return E_ST_NO_CONSTRAINT; + } + } + else + { + // normalize direction + if (!constraint.mTargetDir.isExactlyZero()) + { + constraint.mTargetDir.normVec(); + } + + } + + constraint.mConstraintType = CONSTRAINT_TYPE_POINT; + mConstraints.push_back(constraint); + continue; + } + + if (loadingGlobals && LLStringUtil::compareInsensitive(token, "planar_constraint")==0) + { + Constraint constraint; + + // try reading optional target direction + if(sscanf( /* Flawfinder: ignore */ + mLine, + " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", + &constraint.mChainLength, + &constraint.mEaseInStart, + &constraint.mEaseInStop, + &constraint.mEaseOutStart, + &constraint.mEaseOutStop, + constraint.mSourceJointName, + &constraint.mSourceOffset.mV[VX], + &constraint.mSourceOffset.mV[VY], + &constraint.mSourceOffset.mV[VZ], + constraint.mTargetJointName, + &constraint.mTargetOffset.mV[VX], + &constraint.mTargetOffset.mV[VY], + &constraint.mTargetOffset.mV[VZ], + &constraint.mTargetDir.mV[VX], + &constraint.mTargetDir.mV[VY], + &constraint.mTargetDir.mV[VZ]) != 16) + { + if(sscanf( /* Flawfinder: ignore */ + mLine, + " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", + &constraint.mChainLength, + &constraint.mEaseInStart, + &constraint.mEaseInStop, + &constraint.mEaseOutStart, + &constraint.mEaseOutStop, + constraint.mSourceJointName, + &constraint.mSourceOffset.mV[VX], + &constraint.mSourceOffset.mV[VY], + &constraint.mSourceOffset.mV[VZ], + constraint.mTargetJointName, + &constraint.mTargetOffset.mV[VX], + &constraint.mTargetOffset.mV[VY], + &constraint.mTargetOffset.mV[VZ]) != 13) + { + return E_ST_NO_CONSTRAINT; + } + } + else + { + // normalize direction + if (!constraint.mTargetDir.isExactlyZero()) + { + constraint.mTargetDir.normVec(); + } + + } + + constraint.mConstraintType = CONSTRAINT_TYPE_PLANE; + mConstraints.push_back(constraint); + continue; + } + } + + infile.close() ; + return E_ST_OK; +} void LLBVHLoader::makeTranslation(std::string alias_name, std::string joint_name) { //Translation &newTrans = (foomap.insert(value_type(alias_name, Translation()))).first(); @@ -926,7 +1231,9 @@ void LLBVHLoader::reset() mInitialized = FALSE; mEmoteName = ""; - mTranslations.clear(); + mLineNumber = 0; + mTranslations.clear(); + mConstraints.clear(); } //------------------------------------------------------------------------ @@ -1156,7 +1463,29 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) } } - dp.packS32(0, "num_constraints"); + S32 num_constraints = (S32)mConstraints.size(); + dp.packS32(num_constraints, "num_constraints"); + + for (ConstraintVector::iterator constraint_it = mConstraints.begin(); + constraint_it != mConstraints.end(); + constraint_it++) + { + U8 byte = constraint_it->mChainLength; + dp.packU8(byte, "chain_length"); + + byte = constraint_it->mConstraintType; + dp.packU8(byte, "constraint_type"); + dp.packBinaryDataFixed((U8*)constraint_it->mSourceJointName, 16, "source_volume"); + dp.packVector3(constraint_it->mSourceOffset, "source_offset"); + dp.packBinaryDataFixed((U8*)constraint_it->mTargetJointName, 16, "target_volume"); + dp.packVector3(constraint_it->mTargetOffset, "target_offset"); + dp.packVector3(constraint_it->mTargetDir, "target_dir"); + dp.packF32(constraint_it->mEaseInStart, "ease_in_start"); + dp.packF32(constraint_it->mEaseInStop, "ease_in_stop"); + dp.packF32(constraint_it->mEaseOutStart, "ease_out_start"); + dp.packF32(constraint_it->mEaseOutStop, "ease_out_stop"); + } + return TRUE; } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 01a7c8ad16..47fe409047 100755 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -32,7 +32,6 @@ #include "llmath.h" #include "llapr.h" #include "llbvhconsts.h" -#include const S32 BVH_PARSER_LINE_SIZE = 2048; class LLDataPacker; @@ -228,8 +227,6 @@ class LLBVHLoader friend class LLKeyframeMotion; public: // Constructor -// LLBVHLoader(const char* buffer); - LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map& joint_alias_map ); ~LLBVHLoader(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3c6b1c7903..a006611a45 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1600,6 +1600,7 @@ set_source_files_properties(${viewer_XUI_FILES} list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES}) set(viewer_APPSETTINGS_FILES + app_settings/anim.ini app_settings/cmd_line.xml app_settings/commands.xml app_settings/grass.xml diff --git a/indra/newview/app_settings/anim.ini b/indra/newview/app_settings/anim.ini new file mode 100755 index 0000000000..c24d2749ef --- /dev/null +++ b/indra/newview/app_settings/anim.ini @@ -0,0 +1,2 @@ +Translations 1.0 + diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 47182620d2..f3e845171f 100755 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -1,6 +1,6 @@ - + @@ -11,12 +11,12 @@ - + - + @@ -37,11 +37,11 @@ - + - + - + @@ -49,25 +49,25 @@ - + - + - + - + - + - + - + - + @@ -75,26 +75,26 @@ - + - + - + - + - + - + diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b6924e5904..3b482e1bc0 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -937,27 +937,6 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status) return "unknown"; } -void LLVOAvatar::getLegalJointNames(std::deque& legal_joint_names, - bool include_collision_volumes) -{ - LLAvatarAppearance::joint_alias_map_t alias_map = getJointAliases(); - - std::map::iterator iter; - - for (iter = alias_map.begin(); iter != alias_map.end(); ++iter) - { - legal_joint_names.push_back(iter->first); - } - - if (include_collision_volumes) - { - for (S32 i = 0; i < mNumCollisionVolumes; i++) - { - legal_joint_names.push_back(mCollisionVolumes[i].getName()); - } - } -} - // static void LLVOAvatar::dumpBakedStatus() { diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 29f70fca18..002359ebac 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -147,8 +147,6 @@ public: void collectBakedTextureUUIDs(std::set& ids) const; void collectTextureUUIDs(std::set& ids); void releaseOldTextures(); - void getLegalJointNames(std::deque& legal_joint_names, - bool include_collision_volumes); /*virtual*/ void updateTextures(); LLViewerFetchedTexture* getBakedTextureImage(const U8 te, const LLUUID& uuid); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. -- cgit v1.2.3 From 3bfc2564a685f87dda38d423ca3c32f96efeedf1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 16 Nov 2015 12:53:43 -0500 Subject: SL-201 WIP - avatar_skeleton.xml tweaks for aliases, removed wings and tail from default definition. --- indra/newview/character/avatar_lad.xml | 110 --------------------- indra/newview/character/avatar_skeleton.xml | 38 ++----- .../character/avatar_skeleton_wings_tail.xml | 40 ++++---- 3 files changed, 27 insertions(+), 161 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ac0b8b5704..9ec6428ee6 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -413,116 +413,6 @@ rotation="0 0 0" visible_in_first_person="true" /> - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - @@ -17,22 +9,6 @@ - - - - - - - - - - - - - - - - @@ -43,9 +19,9 @@ - + - + @@ -79,10 +55,10 @@ - + - + @@ -92,10 +68,10 @@ - + - + diff --git a/indra/newview/character/avatar_skeleton_wings_tail.xml b/indra/newview/character/avatar_skeleton_wings_tail.xml index 7a088484d8..f3e845171f 100644 --- a/indra/newview/character/avatar_skeleton_wings_tail.xml +++ b/indra/newview/character/avatar_skeleton_wings_tail.xml @@ -1,6 +1,6 @@ - + @@ -11,12 +11,12 @@ - + - + @@ -37,11 +37,11 @@ - + - + - + @@ -49,25 +49,25 @@ - + - + - + - + - + - + - + - + @@ -75,26 +75,26 @@ - + - + - + - + - + - + -- cgit v1.2.3 From 94d7d6a623d755424c2bd8c2526bff0d46101915 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 17 Nov 2015 16:41:55 -0500 Subject: SL-271 WIP, SL-201 WIP - add support for end point to joints, use for debug rendering display to show bones. --- indra/llappearance/llavatarappearance.cpp | 12 +++++- indra/llcharacter/lljoint.cpp | 1 + indra/llcharacter/lljoint.h | 8 ++++ indra/newview/llspatialpartition.cpp | 11 +++++ indra/newview/llvoavatar.cpp | 48 ++++++++++++++++++++++ indra/newview/llvoavatar.h | 1 + .../xui/en/floater_notifications_tabbed.xml | 6 +-- indra/newview/skins/default/xui/en/menu_viewer.xml | 10 +++++ .../xui/en/panel_notification_list_item.xml | 13 +++--- 9 files changed, 99 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 81834204f5..142120cb6c 100755 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -92,6 +92,7 @@ private: std::string mAliases; BOOL mIsJoint; LLVector3 mPos; + LLVector3 mEnd; LLVector3 mRot; LLVector3 mScale; LLVector3 mPivot; @@ -610,6 +611,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent info->mRot.mV[VZ], LLQuaternion::XYZ)); joint->setScale(info->mScale); joint->setSupport(info->mSupport); + joint->setEnd(info->mEnd); if (info->mIsJoint) { @@ -1572,10 +1574,18 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) return FALSE; } + // BENTO rename leaf->end + static LLStdStringHandle end_string = LLXmlTree::addAttributeString("leaf"); + if (!node->getFastAttributeVector3(end_string, mEnd)) + { + LL_WARNS() << "Bone without end " << mName << LL_ENDL; + mEnd = LLVector3(1.0f, 0.0f, 0.0f); + } + static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support"); if (!node->getFastAttributeString(support_string,mSupport)) { - LL_WARNS() << "Bone without support" << LL_ENDL; + LL_WARNS() << "Bone without support " << mName << LL_ENDL; mSupport = "base"; } diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 2c6278fe45..8fcab454dc 100755 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -109,6 +109,7 @@ void LLJoint::init() mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; mSupport = SUPPORT_BASE; + mEnd = LLVector3(0.0f, 0.0f, 0.0f); } LLJoint::LLJoint() : diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 8d380cdc82..f11cbacaaa 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -117,6 +117,10 @@ public: // describes the skin binding pose LLVector3 mSkinOffset; + // Endpoint of the bone, if applicable. This is only relevant for + // external programs like Blender, and for diagnostic display. + LLVector3 mEnd; + S32 mJointNum; // child joints @@ -156,6 +160,10 @@ public: SupportCategory getSupport() const { return mSupport; } void setSupport( const SupportCategory& support) { mSupport = support; } void setSupport( const std::string& support_string); + + // get/set end point + void setEnd( const LLVector3& end) { mEnd = end; } + const LLVector3& getEnd() const { return mEnd; } // getParent LLJoint *getParent() { return mParent; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5e342099d7..28e038b828 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3216,6 +3216,11 @@ void renderAvatarCollisionVolumes(LLVOAvatar* avatar) avatar->renderCollisionVolumes(); } +void renderAvatarBones(LLVOAvatar* avatar) +{ + avatar->renderBones(); +} + void renderAgentTarget(LLVOAvatar* avatar) { // render these for self only (why, i don't know) @@ -3374,6 +3379,11 @@ public: renderAvatarCollisionVolumes(avatar); } + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) + { + renderAvatarBones(avatar); + } + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) { renderAgentTarget(avatar); @@ -3664,6 +3674,7 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | LLPipeline::RENDER_DEBUG_RAYCAST | LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | + LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | LLPipeline::RENDER_DEBUG_AGENT_TARGET | //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3b482e1bc0..5fed8ce938 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1360,6 +1360,54 @@ void LLVOAvatar::renderCollisionVolumes() addDebugText(ostr.str()); } +void LLVOAvatar::renderBones() +{ + std::ostringstream ostr; + std::ostringstream nullstr; + + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + + for (; iter != end; ++iter) + { + LLJoint* jointp = *iter; + if (!jointp) + { + continue; + } + + ostr << jointp->getName() << ", "; + + jointp->updateWorldMatrix(); + + gGL.pushMatrix(); + gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); + + gGL.diffuseColor3f( 1.f, 0.f, 1.f ); + + gGL.begin(LLRender::LINES); + + LLVector3 v[] = + { + LLVector3(0,0,0), + LLVector3(0,0,0), + }; + v[1] = jointp->getEnd(); + + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[1].mV); + + gGL.end(); + + gGL.popMatrix(); + } + + mDebugText.clear(); + addDebugText(ostr.str()); + addDebugText(nullstr.str()); +} + + void LLVOAvatar::renderJoints() { std::ostringstream ostr; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 002359ebac..f6879c4b78 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -399,6 +399,7 @@ public: F32 getLastSkinTime() { return mLastSkinTime; } U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); + void renderBones(); void renderJoints(); static void deleteCachedImages(bool clearAll=true); static void destroyGL(); diff --git a/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml index afc609de52..c17d2a1f37 100644 --- a/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml +++ b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml @@ -136,15 +136,15 @@ - + - + - + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3f557d0d0f..3b5f3a3184 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3554,6 +3554,16 @@ function="Advanced.ToggleInfoDisplay" parameter="collision skeleton" /> + + + + diff --git a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml index a909028f9f..efaaefd0e4 100644 --- a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml @@ -9,7 +9,6 @@ left="0" width="331" height="202" - can_resize="true" layout="topleft" follows="left|top|right|bottom" > @@ -45,12 +44,12 @@ - + - + - + + + + + + + + + + - media_plugin_cef + media_plugin_libvlc @@ -207,7 +207,7 @@ movie - media_plugin_cef + media_plugin_libvlc @@ -449,7 +449,7 @@ movie - media_plugin_cef + media_plugin_libvlc @@ -460,10 +460,21 @@ movie - media_plugin_cef + media_plugin_libvlc - + + + + movie + + + media_plugin_libvlc + + + @@ -471,7 +482,7 @@ movie - media_plugin_cef + media_plugin_libvlc @@ -482,7 +493,7 @@ movie - media_plugin_cef + media_plugin_libvlc -- cgit v1.2.3 From 182f2a48159e231149227e1cd606b3d7ead04dcd Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 11 May 2016 16:08:25 -0400 Subject: SL-315 - resetSkeleton(), working for bones at least partially, still some issues with collision volumes --- indra/llappearance/llpolyskeletaldistortion.cpp | 88 +++++++++++++------------ indra/newview/llvoavatar.cpp | 48 ++++++++++++-- 2 files changed, 86 insertions(+), 50 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index 484969a9d9..f75603e083 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -134,55 +134,57 @@ LLPolySkeletalDistortion::~LLPolySkeletalDistortion() BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) { - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - - LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; - for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) + //llassert(mInfo == NULL); + if (info->mID < 0) + { + return FALSE; + } + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + + LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; + for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) + { + LLPolySkeletalBoneInfo *bone_info = &(*iter); + LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); + if (!joint) { - LLPolySkeletalBoneInfo *bone_info = &(*iter); - LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); - if (!joint) - { - LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL; - continue; - } + LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL; + continue; + } - if (mJointScales.find(joint) != mJointScales.end()) - { - LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; - } + //if (mJointScales.find(joint) != mJointScales.end()) + //{ + // LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; + //} - // store it - mJointScales[joint] = bone_info->mScaleDeformation; + // store it + mJointScales[joint] = bone_info->mScaleDeformation; - // apply to children that need to inherit it - for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); - iter != joint->mChildren.end(); ++iter) - { - LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); - if (child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info->mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } - } + // apply to children that need to inherit it + for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); + if (child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info->mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } + } - if (bone_info->mHasPositionDeformation) - { - if (mJointOffsets.find(joint) != mJointOffsets.end()) - { - LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; - } - mJointOffsets[joint] = bone_info->mPositionDeformation; - } + if (bone_info->mHasPositionDeformation) + { + //if (mJointOffsets.find(joint) != mJointOffsets.end()) + //{ + // LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; + //} + mJointOffsets[joint] = bone_info->mPositionDeformation; } - return TRUE; + } + return TRUE; } /*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 37c5e84347..e82f24a069 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1802,22 +1802,56 @@ void LLVOAvatar::buildCharacter() } //----------------------------------------------------------------------------- -// resetSkeleton() +// resetVisualParams() //----------------------------------------------------------------------------- void LLVOAvatar::resetVisualParams() { + // SKELETAL DISTORTIONS + { + LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; + LLPolySkeletalDistortion *param = dynamic_cast(getVisualParam(info->getID())); + *param = LLPolySkeletalDistortion(this); + llassert(param); + if (!param->setInfo(info)) + { + llassert(false); + } + } + } #if 0 - for (LLVisualParam *param = getFirstVisualParam(); - param; - param = getNextVisualParam()) + // avatar_lad.xml : + for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); + ++iter) { - if (param->isAnimating()) + LLDriverParamInfo *info = *iter; + LLDriverParam* driver_param = new LLDriverParam( this ); + if (driver_param->setInfo(info)) { - continue; + addVisualParam( driver_param ); + driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; + if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) + { + LL_WARNS() << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << LL_ENDL; + continue; + } + } + else + { + delete driver_param; + LL_WARNS() << "avatar file: driver_param->parseData() failed" << LL_ENDL; + return FALSE; } - param->setLastWeight(param->getDefaultWeight()); } #endif + + } //----------------------------------------------------------------------------- -- cgit v1.2.3 From d0dea44c010ec4e747b139ce55013e3203ba980a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 May 2016 10:57:08 -0400 Subject: SL-315 - resetSkeleton(). Still some small scale discrepancies, visually pretty good. --- indra/llappearance/llpolymorph.cpp | 17 ++++++++++++++++- indra/llappearance/llpolymorph.h | 2 ++ indra/newview/llvoavatar.cpp | 21 ++++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 80e81936fb..2cb4c65d7c 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -369,7 +369,8 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName) { - mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], + mVolumeMorphs.push_back( + LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], volume_info->mScale, volume_info->mPos)); break; @@ -731,6 +732,20 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 apply(mLastSex); } +void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) +{ + // now apply volume changes + for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ ) + { + LLPolyVolumeMorph* volume_morph = &(*iter); + LLVector3 scale_delta = volume_morph->mScale * delta_weight; + LLVector3 pos_delta = volume_morph->mPos * delta_weight; + + volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta); + // SL-315 + volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta); + } +} //----------------------------------------------------------------------------- // LLPolyVertexMask() diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 3c2c68079c..c6133cd831 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -182,6 +182,8 @@ public: void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } + void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() + void* operator new(size_t size) { return ll_aligned_malloc_16(size); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e82f24a069..9286a70886 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1859,7 +1859,7 @@ void LLVOAvatar::resetVisualParams() //----------------------------------------------------------------------------- void LLVOAvatar::resetSkeleton() { - LL_DEBUGS("Avatar") << avString() << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << " reset starts" << LL_ENDL; if (!mLastProcessedAppearance) { LL_WARNS() << "Can't reset avatar; no appearance message has been received yet." << LL_ENDL; @@ -1883,15 +1883,34 @@ void LLVOAvatar::resetSkeleton() bool ignore_hud_joints = true; initAttachmentPoints(ignore_hud_joints); + // Fix up collision volumes + for (LLVisualParam *param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + LLPolyMorphTarget *poly_morph = dynamic_cast(param); + if (poly_morph) + { + // This is a kludgy way to correct for the fact that the + // collision volumes have been reset out from under the + // poly morph sliders. + F32 delta_weight = poly_morph->getLastWeight() - poly_morph->getDefaultWeight(); + poly_morph->applyVolumeChanges(delta_weight); + } + } + // Reset tweakable params to preserved state // Apply params applyParsedAppearanceMessage(*mLastProcessedAppearance); + updateVisualParams(); // Restore attachment pos overrides rebuildAttachmentPosOverrides(); // Restart animations + + LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL; } //----------------------------------------------------------------------------- -- cgit v1.2.3 From 1b5af4be298198cedc407b6b294b2d71129d7731 Mon Sep 17 00:00:00 2001 From: ruslantproductengine Date: Fri, 13 May 2016 18:47:23 +0300 Subject: Add invert texture coordinates for media textures. --- indra/llrender/llglslshader.cpp | 22 +++++++++++ indra/llrender/llglslshader.h | 1 + indra/llrender/llrender.cpp | 8 ++++ indra/llrender/llrender.h | 1 + indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 3 +- .../shaders/class1/deferred/diffuseV.glsl | 11 ++++++ .../shaders/class1/deferred/fullbrightV.glsl | 11 ++++++ .../shaders/class1/objects/fullbrightV.glsl | 13 +++++++ .../shaders/class1/objects/simpleV.glsl | 12 +++++- indra/newview/lldrawpool.cpp | 45 ++++++++++++++++++++++ 11 files changed, 126 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 52b8de8365..8790b1ed7d 100755 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1278,6 +1278,28 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c } } +void LLGLSLShader::uniform1b(U32 index, GLboolean x) +{ + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map::iterator iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1iARB(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); + } + } + } +} + GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) { GLint ret = -1; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 0746e8760a..8663a5a5ff 100755 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -125,6 +125,7 @@ public: void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void uniform1b(U32 index, GLboolean b); void setMinimumAlpha(F32 minimum); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 69420dd0bb..b5ed67f66a 100755 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1466,6 +1466,14 @@ U32 LLRender::getMatrixMode() return mMatrixMode; } +void LLRender::setInverseTexCoordByY(bool v) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (shader) + { + shader->uniform1b(LLShaderMgr::INVERSE_TEX_Y, v); + } +} void LLRender::loadIdentity() { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index a67fb8da52..4c3547f8e4 100755 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -355,6 +355,7 @@ public: void multMatrix(const GLfloat* m); void matrixMode(U32 mode); U32 getMatrixMode(); + void setInverseTexCoordByY(bool v); const glh::matrix4f& getModelviewMatrix(); const glh::matrix4f& getProjectionMatrix(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b2be3cc3b6..79e0b3da28 100755 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1206,6 +1206,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("display_gamma"); + mReservedUniforms.push_back("invert_tex_y"); llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 394b38f832..50b7c8b9d9 100755 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -215,7 +215,8 @@ public: TERRAIN_ALPHARAMP, SHINY_ORIGIN, -DISPLAY_GAMMA, + DISPLAY_GAMMA, + INVERSE_TEX_Y, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 3c026796c8..7e83389f6e 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -26,6 +26,13 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; +uniform bool invert_tex_y = false; +const mat4 invTexM = mat4( + 1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +); ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; @@ -44,6 +51,10 @@ void main() //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + if(invert_tex_y) + { + vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; + } passTextureIndex(); vary_normal = normalize(normal_matrix * normal); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 8e899e3e0f..2595712882 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -26,6 +26,13 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; +uniform bool invert_tex_y = false; +const mat4 invTexM = mat4( + 1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +); ATTRIBUTE vec3 position; @@ -62,6 +69,10 @@ void main() #endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + if(invert_tex_y) + { + vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; + } calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index fc20d3270e..a8efcd9857 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -26,6 +26,14 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; + +uniform bool invert_tex_y = false; +const mat4 invTexM = mat4( + 1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +); ATTRIBUTE vec3 position; void passTextureIndex(); @@ -49,6 +57,11 @@ void main() vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + + if(invert_tex_y) + { + vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; + } calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index 37a20383e2..c744dc1397 100755 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -27,6 +27,13 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; +uniform bool invert_tex_y = false; +const mat4 invTexM = mat4( + 1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +); ATTRIBUTE vec3 position; void passTextureIndex(); @@ -51,7 +58,10 @@ void main() gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy; - + if(invert_tex_y) + { + vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; + } vec3 norm = normalize(normal_matrix * normal); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index f74164aea6..a6cf917cbd 100755 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -473,6 +473,10 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba if (params.mTextureList[i].notNull()) { gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + if (LLViewerTexture::MEDIA_TEXTURE == params.mTextureList[i]->getType()) + { + gGL.setInverseTexCoordByY(true); + } } } } @@ -482,13 +486,54 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { params.mTexture->addTextureStats(params.mVSize); gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + + if (!gPipeline.mVertexShadersEnabled) + { + if (LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType() && !params.mTextureMatrix) + { + static const float fIdntInvY[] = { + 1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)fIdntInvY); + gPipeline.mTextureMatrixOps++; + + tex_setup = true; + } + } + else + { + gGL.setInverseTexCoordByY(LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType()); + } + if (params.mTextureMatrix) { tex_setup = true; gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + + if (LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType() && !gPipeline.mVertexShadersEnabled) + { + static const float fIdntInvY[] = { + 1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + + gGL.multMatrix(fIdntInvY); + gPipeline.mMatrixOpCount++; + } + gPipeline.mTextureMatrixOps++; + + tex_setup = true; } } else -- cgit v1.2.3 From f0e9566b90183081daef4ff8b534093fbcf73e6d Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 13 May 2016 13:09:12 -0700 Subject: pull in unflipped version of LLCEFLib --- indra/media_plugins/cef/media_plugin_cef.cpp | 2 +- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 8d9d1dd975..d61bd680df 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -488,7 +488,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueU32("internalformat", GL_RGB); message.setValueU32("format", GL_BGRA); message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); + message.setValueBoolean("coords_opengl", false); sendMessage(message); } else if (message_name == "set_user_data_path") diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 08716e1a1c..920c32f1f7 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -56,6 +56,7 @@ class MediaPluginLibVLC : void resetVLC(); static void* lock(void* data, void** p_pixels); + static void unlock(void* data, void* id, void* const* raw_pixels); static void display(void* data, void* id); libvlc_instance_t* gLibVLC; @@ -109,6 +110,14 @@ void* MediaPluginLibVLC::lock(void* data, void** p_pixels) return NULL; } +///////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels) +{ + // nothing to do here for the moment. + // we can modify the raw_pixels here if we want to. +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::display(void* data, void* id) @@ -188,7 +197,7 @@ void MediaPluginLibVLC::playMedia() gVLCCallbackContext.texture_pixels = mPixels; gVLCCallbackContext.mp = gLibVLCMediaPlayer; - libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, NULL, display, &gVLCCallbackContext); + libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * 4); libvlc_media_player_play(gLibVLCMediaPlayer); } @@ -281,7 +290,6 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) { if(message_name == "init") { - mDepth = 4; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); message.setValueS32("default_width", 1024); message.setValueS32("default_height", 1024); @@ -289,7 +297,7 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) message.setValueU32("internalformat", GL_RGB); message.setValueU32("format", GL_BGRA_EXT); message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); + message.setValueBoolean("coords_opengl", false); sendMessage(message); } else if(message_name == "size_change") -- cgit v1.2.3 From 09e68a49535a15f89b2c28e523a81fed1770ee61 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 13 May 2016 16:43:18 -0700 Subject: Additional set of changes to use vlc-bin package --- indra/cmake/LibVLCPlugin.cmake | 6 ++++++ indra/media_plugins/libvlc/CMakeLists.txt | 3 ++- indra/newview/viewer_manifest.py | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake index 286a8d8d1b..0d2c46bac0 100644 --- a/indra/cmake/LibVLCPlugin.cmake +++ b/indra/cmake/LibVLCPlugin.cmake @@ -6,11 +6,17 @@ if (USESYSTEMLIBS) set(LIBVLCPLUGIN OFF CACHE BOOL "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") else (USESYSTEMLIBS) + use_prebuilt_binary(vlc-bin) set(LIBVLCPLUGIN ON CACHE BOOL "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") + set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc) endif (USESYSTEMLIBS) if (WINDOWS) + set(VLC_PLUGIN_LIBRARIES + libvlc.lib + libvlccore.lib + ) elseif (DARWIN) elseif (LINUX) endif (WINDOWS) diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt index 1b6adaa290..535d29125b 100644 --- a/indra/media_plugins/libvlc/CMakeLists.txt +++ b/indra/media_plugins/libvlc/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${VLC_INCLUDE_DIR} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -53,7 +54,7 @@ target_link_libraries(media_plugin_libvlc ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} ${LLCOMMON_LIBRARIES} - ${LIBVLC_PLUGIN_LIBRARIES} + ${VLC_PLUGIN_LIBRARIES} ${PLUGIN_API_WINDOWS_LIBRARIES} ) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 9302dd8e03..e7f517518b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -547,6 +547,12 @@ class Windows_i686_Manifest(ViewerManifest): self.path("zh-TW.pak") self.end_prefix() + if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): + self.path("libvlc.dll") + self.path("libvlccore.dll") + self.path("plugins/") + self.end_prefix() + # pull in the crash logger and updater from other projects # tag:"crash-logger" here as a cue to the exporter self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], -- cgit v1.2.3 From 50ab1e57ec21f2009013b3bc061047887cdd07d5 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 16 May 2016 10:58:39 -0700 Subject: Added support for some transport controls (pause/play/stop) and setting media volume level. --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 41 +++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 920c32f1f7..92bfc15113 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -198,7 +198,7 @@ void MediaPluginLibVLC::playMedia() gVLCCallbackContext.mp = gLibVLCMediaPlayer; libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); - libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * 4); + libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); libvlc_media_player_play(gLibVLCMediaPlayer); } @@ -338,6 +338,45 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) playMedia(); } } + else + if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if (message_name == "stop") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_stop(gLibVLCMediaPlayer); + } + } + else if (message_name == "start") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_play(gLibVLCMediaPlayer); + } + } + else if (message_name == "pause") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_pause(gLibVLCMediaPlayer); + } + } + else if (message_name == "seek") + { + } + else if (message_name == "set_loop") + { + } + else if (message_name == "set_volume") + { + if (gLibVLCMediaPlayer) + { + F64 volume = message_in.getValueReal("volume"); + libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); + } + } + } } } -- cgit v1.2.3 From 82111ecbde4bacd4cbd5ae5d076876d0ddedd04d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 17 May 2016 16:06:27 -0400 Subject: SL-315 - resetSkeleton() fixes, mostly to get better behavior with non-self avs --- indra/llappearance/llavatarappearance.cpp | 2 +- indra/llappearance/lldriverparam.h | 4 +++ indra/newview/character/avatar_lad.xml | 2 +- indra/newview/llvoavatar.cpp | 49 ++++++++++++------------------- indra/newview/llvoavatar.h | 2 +- 5 files changed, 26 insertions(+), 33 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 4f01665449..2ce43436db 100755 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -601,7 +601,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent } // add to parent - if (parent) + if (parent && (joint->getParent()!=parent)) { parent->addChild( joint ); } diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index f71c930e5e..05b4f2252e 100755 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -128,6 +128,10 @@ public: S32 getDrivenParamsCount() const; const LLViewerVisualParam* getDrivenParam(S32 index) const; + typedef std::vector entry_list_t; + entry_list_t& getDrivenList() { return mDriven; } + void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; } + protected: LLDriverParam(const LLDriverParam& pOther); F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 53faf1149b..fcb4709c6c 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -3204,7 +3204,7 @@ id="30024" group="1" name="Wide_Eyes" - value_min="-2" + value_min="-1.5" value_max="2"> diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 9286a70886..23008839ee 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1806,7 +1806,7 @@ void LLVOAvatar::buildCharacter() //----------------------------------------------------------------------------- void LLVOAvatar::resetVisualParams() { - // SKELETAL DISTORTIONS + // Skeletal params { LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); @@ -1823,35 +1823,23 @@ void LLVOAvatar::resetVisualParams() } } } -#if 0 - // avatar_lad.xml : + + // Driver parameters for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); iter != sAvatarXmlInfo->mDriverInfoList.end(); ++iter) { LLDriverParamInfo *info = *iter; - LLDriverParam* driver_param = new LLDriverParam( this ); - if (driver_param->setInfo(info)) - { - addVisualParam( driver_param ); - driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; - if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) - { - LL_WARNS() << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << LL_ENDL; - continue; - } - } - else - { - delete driver_param; - LL_WARNS() << "avatar file: driver_param->parseData() failed" << LL_ENDL; - return FALSE; - } + LLDriverParam *param = dynamic_cast(getVisualParam(info->getID())); + LLDriverParam::entry_list_t driven_list = param->getDrivenList(); + *param = LLDriverParam(this); + llassert(param); + if (!param->setInfo(info)) + { + llassert(false); + } + param->setDrivenList(driven_list); } -#endif - - } //----------------------------------------------------------------------------- @@ -1871,7 +1859,7 @@ void LLVOAvatar::resetSkeleton() // Clear all attachment pos overrides clearAttachmentPosOverrides(); - // Reset all params to default state, without propagating changes downstream. + // Reset some params to default state, without propagating changes downstream. resetVisualParams(); // Reset all bones and collision volumes to their initial skeleton state. @@ -1900,8 +1888,8 @@ void LLVOAvatar::resetSkeleton() } // Reset tweakable params to preserved state - // Apply params - applyParsedAppearanceMessage(*mLastProcessedAppearance); + bool slam_params = true; + applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); updateVisualParams(); @@ -7837,10 +7825,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mLastUpdateReceivedCOFVersion = this_update_cof_version; mLastProcessedAppearance = contents; - applyParsedAppearanceMessage(*contents); + bool slam_params = false; + applyParsedAppearanceMessage(*contents, slam_params); } -void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents) +void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params) { S32 num_params = contents.mParamWeights.size(); ESex old_sex = getSex(); @@ -7900,7 +7889,7 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte params_changed = TRUE; params_changed_count++; - if(is_first_appearance_message) + if(is_first_appearance_message || slam_params) { //LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL; param->setWeight(newWeight); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 91de5c4217..cca9f0dd1a 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -679,7 +679,7 @@ protected: public: void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg); void processAvatarAppearance(LLMessageSystem* mesgsys); - void applyParsedAppearanceMessage(LLAppearanceMessageContents& contents); + void applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params); void hideSkirt(); void startAppearanceAnimation(); -- cgit v1.2.3 From bb2c147c26efad32f72fd7cdf1378824a4b0085d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 18 May 2016 09:06:46 -0400 Subject: SL-315 - fix for max/linux build failure, additional lad validation in skel_tool.py --- indra/llappearance/lldriverparam.h | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 05b4f2252e..f278dcc2e2 100755 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -139,7 +139,6 @@ protected: LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder - typedef std::vector entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; // Backlink only; don't make this an LLPointer. -- cgit v1.2.3 From e8afa4c413efac9f58fbfccb1c14c114317a383e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 18 May 2016 17:07:54 -0400 Subject: SL-315 - fixed collision volume scale issue in resetSkeleton() --- indra/llappearance/llpolyskeletaldistortion.cpp | 13 +++++++++++-- indra/newview/llvoavatar.cpp | 19 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index f75603e083..fdce8d97ce 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -34,6 +34,7 @@ #include "llpolymorph.h" #include "llwearable.h" #include "llfasttimer.h" +#include "llcallstack.h" #include "llpolyskeletaldistortion.h" @@ -134,7 +135,6 @@ LLPolySkeletalDistortion::~LLPolySkeletalDistortion() BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) { - //llassert(mInfo == NULL); if (info->mID < 0) { return FALSE; @@ -154,6 +154,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) continue; } + // BENTO remove? //if (mJointScales.find(joint) != mJointScales.end()) //{ // LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; @@ -177,6 +178,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) if (bone_info->mHasPositionDeformation) { + // BENTO remove? //if (mJointOffsets.find(joint) != mJointOffsets.end()) //{ // LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL; @@ -213,9 +215,16 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex ) joint = iter->first; LLVector3 newScale = joint->getScale(); LLVector3 scaleDelta = iter->second; - newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); + LLVector3 offset = (effective_weight - mLastWeight) * scaleDelta; + newScale = newScale + offset; //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached // needed? // joint->storeScaleForReset( newScale ); + + // BENTO debugging stuff can be pulled. + std::stringstream ostr; + ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; + LLScopedContextString str(ostr.str()); + joint->setScale(newScale); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 23008839ee..fb7b7d3ef8 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1854,20 +1854,30 @@ void LLVOAvatar::resetSkeleton() return; } - // Stop all animations - // Clear all attachment pos overrides clearAttachmentPosOverrides(); + // Note that we call buildSkeleton twice in this function. The first time is + // just to get the right scale for the collision volumes, because + // this will be used in setting the mJointScales for the + // LLPolySkeletalDistortions of which the CVs are children. + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + LL_ERRS() << "Error resetting skeleton" << LL_ENDL; + } + // Reset some params to default state, without propagating changes downstream. resetVisualParams(); - // Reset all bones and collision volumes to their initial skeleton state. + // Now we have to reset the skeleton again, because its state + // got clobbered by the resetVisualParams() calls + // above. if( !buildSkeleton(sAvatarSkeletonInfo) ) { LL_ERRS() << "Error resetting skeleton" << LL_ENDL; } - // Reset attachment points + + // Reset attachment points (buildSkeleton only does bones and CVs) bool ignore_hud_joints = true; initAttachmentPoints(ignore_hud_joints); @@ -1897,6 +1907,7 @@ void LLVOAvatar::resetSkeleton() rebuildAttachmentPosOverrides(); // Restart animations + resetAnimations(); LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL; } -- cgit v1.2.3 From 357f6d04edb354f12ae052f35c65cfd87ba4cb2d Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Fri, 20 May 2016 01:45:12 +0300 Subject: MAINT-6419 Show the release notes when first starting a new viewer --- indra/newview/app_settings/settings.xml | 11 ++++++++ indra/newview/llappviewer.cpp | 33 ++++++++++++++++++++++ .../default/xui/en/panel_preferences_setup.xml | 12 ++++++++ 3 files changed, 56 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4912f27e70..7bcbf819e4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13276,6 +13276,17 @@ Value 1 + UpdaterShowReleaseNotes + + Comment + Enables displaying of the Release notes in a web floater after update. + Persist + 1 + Type + Boolean + Value + 1 + UploadBakedTexOld Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6bc1f67e32..29680093f9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1220,6 +1220,8 @@ bool LLAppViewer::init() boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + showReleaseNotesIfRequired(); + return true; } @@ -5799,6 +5801,37 @@ void LLAppViewer::launchUpdater() // LLAppViewer::instance()->forceQuit(); } +/** +* Check if user is running a new version of the viewer. +* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. +*/ +void LLAppViewer::showReleaseNotesIfRequired() +{ + if (!gLastRunVersion.empty() && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")) + { + try + { + boost::regex expr("(?[\\w\\s]+)\\s(?\\d+)\\.(?\\d+)\\.(?\\d+)\\.(?\\d+)", boost::regex::perl | boost::regex::icase); + boost::smatch matches; + if (boost::regex_search(gLastRunVersion, matches, expr)) + { + if (LLVersionInfo::getChannel() == matches["chan"] && // don't show Release Notes when changing a channel + (LLVersionInfo::getBuild() > std::stoi(matches["build"]) + || LLVersionInfo::getPatch() > std::stoi(matches["patch"]) + || LLVersionInfo::getMinor() > std::stoi(matches["min"]) + || LLVersionInfo::getMajor() > std::stoi(matches["maj"]))) + { + LLSD info(getViewerInfo()); + LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); + } + } + } + catch (boost::regex_error& e) + { + LL_WARNS() << "Can't parse previous run version, regex errpr: " << e.what() << LL_ENDL; + } + } +} //virtual void LLAppViewer::setMasterSystemAudioMute(bool mute) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 0b605cf6f7..c20f9b2c51 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -273,6 +273,18 @@ name="update_willing_to_test" width="400" top_pad="5"/> + Date: Sun, 22 May 2016 19:03:11 -0400 Subject: SL-344 - provisional slider fixes --- indra/newview/character/avatar_lad.xml | 144 +++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 38bcd88078..f96a13bab4 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -840,6 +840,10 @@ name="mKneeRight" scale="0.12 0.12 0" /> + + @@ -955,6 +959,10 @@ scale="0 0 0" offset="0 -.004 0" /> + + + + @@ -1052,6 +1064,10 @@ name="mKneeLeft" scale="0 0 -.05" /> + + @@ -1392,13 +1408,13 @@ name="mFaceNoseBase" scale="0 0 0" offset=".005 0 0" /> - - - @@ -1407,37 +1423,37 @@ name="mFaceLipUpperLeft" scale="0 0 0" offset="0.005 0 0" /> - + - + - + offset="0.004 0 0" /> + - + offset="0.004 0 0" /> + - + offset="0.004 0 0" /> + - + offset="0.004 0 0" /> + - + + offset="0.012 0 0" /> + offset="0.012 0 0" /> + + @@ -1778,6 +1799,7 @@ name="mFaceLipLowerRight" scale="1 1 1" offset="0 0 0" /> + @@ -1801,6 +1823,17 @@ name="mFootLeft" scale="0 0 0" offset="0 0 -.08" /> + + + + + @@ -1824,6 +1857,17 @@ name="mFootLeft" scale="0 0 0" offset="0 0 -.07" /> + + + + + @@ -3924,7 +3968,7 @@ - + - - - - - + - + - + + + + + + + + + + + + + + + + max1="1" max2="1" min2="1" /> + + + @@ -13879,8 +13953,8 @@ render_pass="bump"> edit_group="hair_style" edit_group_order="16" name="Hair Tilt" - label_min="Hair Tilted Left" - label_max="Hair Tilted Right" + label_min="Left" + label_max="Right" value_min="0" value_max="1" value_default=".5" @@ -14757,7 +14831,7 @@ render_pass="bump"> - + -- cgit v1.2.3 From 0318e3616702b19c088f4cd6138b768d45b7ef11 Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Tue, 24 May 2016 21:59:58 +0300 Subject: MAINT-6419 Simplified the version check + buildfix --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llappviewer.cpp | 25 +++---------------------- indra/newview/llappviewer.h | 2 ++ 3 files changed, 6 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7bcbf819e4..57a9db9337 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13285,7 +13285,7 @@ Type Boolean Value - 1 + 1 UploadBakedTexOld diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 29680093f9..acbcb4f8b7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5807,29 +5807,10 @@ void LLAppViewer::launchUpdater() */ void LLAppViewer::showReleaseNotesIfRequired() { - if (!gLastRunVersion.empty() && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")) + if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")) { - try - { - boost::regex expr("(?[\\w\\s]+)\\s(?\\d+)\\.(?\\d+)\\.(?\\d+)\\.(?\\d+)", boost::regex::perl | boost::regex::icase); - boost::smatch matches; - if (boost::regex_search(gLastRunVersion, matches, expr)) - { - if (LLVersionInfo::getChannel() == matches["chan"] && // don't show Release Notes when changing a channel - (LLVersionInfo::getBuild() > std::stoi(matches["build"]) - || LLVersionInfo::getPatch() > std::stoi(matches["patch"]) - || LLVersionInfo::getMinor() > std::stoi(matches["min"]) - || LLVersionInfo::getMajor() > std::stoi(matches["maj"]))) - { - LLSD info(getViewerInfo()); - LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); - } - } - } - catch (boost::regex_error& e) - { - LL_WARNS() << "Can't parse previous run version, regex errpr: " << e.what() << LL_ENDL; - } + LLSD info(getViewerInfo()); + LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); } } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b5e674bd7b..07bef11dbc 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -254,6 +254,8 @@ private: void sendLogoutRequest(); void disconnectViewer(); + + void showReleaseNotesIfRequired(); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. -- cgit v1.2.3 From 7d54c62016c1362fc0f5fd69acda58c61aed5b76 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 25 May 2016 20:37:52 +0300 Subject: MAINT-6397 cut items should not go to trash --- indra/llui/llfolderviewitem.cpp | 23 ++++++++++++++++++++++- indra/llui/llfolderviewitem.h | 8 ++++++-- indra/llui/llfolderviewmodel.h | 1 + indra/newview/llinventorybridge.cpp | 14 +++++++++++--- indra/newview/llinventorybridge.h | 1 + indra/newview/llinventoryfilter.cpp | 17 +++++------------ 6 files changed, 46 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5eb5ca4f82..14a07d0e90 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -127,6 +127,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mIsSelected( FALSE ), mIsCurSelection( FALSE ), mSelectPending(FALSE), + mIsItemCut(false), + mCutGeneration(0), mLabelStyle( LLFontGL::NORMAL ), mHasVisibleChildren(FALSE), mIsFolderComplete(true), @@ -694,6 +696,19 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsCurSelection; } +/*virtual*/ bool LLFolderViewItem::isFadeItem() +{ + LLClipboard& clipboard = LLClipboard::instance(); + if (mCutGeneration != clipboard.getGeneration()) + { + mCutGeneration = clipboard.getGeneration(); + mIsItemCut = clipboard.isCutMode() + && ((getParentFolder() && getParentFolder()->isFadeItem()) + || getViewModelItem()->isCutToClipboard()); + } + return mIsItemCut; +} + void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { @@ -875,6 +890,12 @@ void LLFolderViewItem::draw() } LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; + + if (isFadeItem()) + { + // Fade out item color to indicate it's being cut + color.mV[VALPHA] *= 0.5f; + } drawLabel(font, text_left, y, color, right_x); //--------------------------------------------------------------------------------// @@ -882,7 +903,7 @@ void LLFolderViewItem::draw() // if (!mLabelSuffix.empty()) { - font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 0322c8836d..61c39e0175 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -121,8 +121,11 @@ protected: mIsMouseOverTitle, mAllowWear, mAllowDrop, - mSelectPending; - + mSelectPending, + mIsItemCut; + + S32 mCutGeneration; + LLUIColor mFontColor; LLUIColor mFontHighlightColor; @@ -145,6 +148,7 @@ protected: virtual void addFolder(LLFolderViewFolder*) { } virtual bool isHighlightAllowed(); virtual bool isHighlightActive(); + virtual bool isFadeItem(); virtual bool isFlashing() { return false; } virtual void setFlashState(bool) { } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index a395af537a..641241a88c 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -173,6 +173,7 @@ public: virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; virtual BOOL cutToClipboard() = 0; + virtual bool isCutToClipboard() { return false; }; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 26c9b40fb1..f4bf38f65d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -286,6 +286,16 @@ BOOL LLInvFVBridge::cutToClipboard() return FALSE; } +// virtual +bool LLInvFVBridge::isCutToClipboard() +{ + if (LLClipboard::instance().isCutMode()) + { + return LLClipboard::instance().isOnClipboard(mUUID); + } + return false; +} + // Callback for cutToClipboard if DAMA required... BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response) { @@ -307,9 +317,7 @@ BOOL LLInvFVBridge::perform_cutToClipboard() if (obj && isItemMovable() && isItemRemovable()) { LLClipboard::instance().setCutMode(true); - BOOL added_to_clipboard = LLClipboard::instance().addToClipboard(mUUID); - removeObject(&gInventory, mUUID); // Always perform the remove even if the object couldn't make it to the clipboard - return added_to_clipboard; + return LLClipboard::instance().addToClipboard(mUUID); } return FALSE; } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 9053c61171..df25e01688 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -116,6 +116,7 @@ public: virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard(); + virtual bool isCutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 003bbcafed..e995c138b4 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -84,21 +84,18 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { const LLFolderViewModelItemInventory* listener = dynamic_cast(item); - // Clipboard cut items are *always* filtered so we need this value upfront - const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - return passed_clipboard; + return true; } bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true); passed = passed && checkAgainstFilterType(listener); passed = passed && checkAgainstPermissions(listener); passed = passed && checkAgainstFilterLinks(listener); - passed = passed && passed_clipboard; return passed; } @@ -108,9 +105,8 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true); const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); - const bool passed_clipboard = checkAgainstClipboard(item->getUUID()); - return passed_filtertype && passed_permissions && passed_clipboard && passed_string; + return passed_filtertype && passed_permissions && passed_string; } bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const @@ -129,13 +125,10 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { - // Always check against the clipboard - const BOOL passed_clipboard = checkAgainstClipboard(folder_id); - // we're showing all folders, overriding filter if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) { - return passed_clipboard; + return true; } // when applying a filter, matching folders get their contents downloaded first @@ -201,7 +194,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const LLViewerInventoryItem* item = gInventory.getItem(folder_id); if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) { - return passed_clipboard; + return true; } if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) @@ -216,7 +209,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return false; } - return passed_clipboard; + return true; } bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const -- cgit v1.2.3 From 7a7973c6a25c8a2ba08969b11f93a2c701051855 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 25 May 2016 16:40:08 -0400 Subject: SL-315 - arche_tool.py updates, resetSkeleton() now preserves mPelvis state, forces all params to be updated. --- indra/newview/llvoavatar.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0728509bcd..25565715c2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1851,6 +1851,10 @@ void LLVOAvatar::resetSkeleton() return; } + // Save mPelvis state + LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); + LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation(); + // Clear all attachment pos overrides clearAttachmentPosOverrides(); @@ -1903,6 +1907,10 @@ void LLVOAvatar::resetSkeleton() // Restore attachment pos overrides rebuildAttachmentPosOverrides(); + // Restore mPelvis state + getJoint("mPelvis")->setRotation(pelvis_rot); + getJoint("mPelvis")->setPosition(pelvis_pos); + // Restart animations resetAnimations(); @@ -7855,7 +7863,7 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte LLVisualParam* param = contents.mParams[i]; F32 newWeight = contents.mParamWeights[i]; - if (is_first_appearance_message || (param->getWeight() != newWeight)) + if (slam_params || is_first_appearance_message || (param->getWeight() != newWeight)) { params_changed = TRUE; params_changed_count++; -- cgit v1.2.3 From f3507631eae59ea2e662150180de48efc544b8e6 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 26 May 2016 18:26:43 +0300 Subject: linux build fix --- indra/llui/llfolderviewitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 14a07d0e90..3d618548c4 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -903,7 +903,7 @@ void LLFolderViewItem::draw() // if (!mLabelSuffix.empty()) { - font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : sSuffixColor, + font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } -- cgit v1.2.3 From 817ae347744eab55ee1f8084102fbc8dc5195f3a Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 26 May 2016 18:09:11 +0300 Subject: MAINT-6438 Add new alert to viewer for too much inventory in coalesced objects --- indra/newview/skins/default/xui/en/notifications.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dfde38bc5f..0e9dcae0ba 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9835,6 +9835,17 @@ Can't move object '[OBJECT_NAME]' to You don't have permission to modify that object + + fail + Too many objects with large inventory are selected. Please select fewer objects and try again. + + + Date: Thu, 26 May 2016 12:52:09 -0400 Subject: SL-117, SL-315 - resetSkeleton() tweaks, additional validation of skeleton file --- indra/newview/llvoavatar.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 25565715c2..0423f0e380 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1852,8 +1852,8 @@ void LLVOAvatar::resetSkeleton() } // Save mPelvis state - LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); - LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation(); + //LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); + //LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation(); // Clear all attachment pos overrides clearAttachmentPosOverrides(); @@ -1908,11 +1908,14 @@ void LLVOAvatar::resetSkeleton() rebuildAttachmentPosOverrides(); // Restore mPelvis state - getJoint("mPelvis")->setRotation(pelvis_rot); - getJoint("mPelvis")->setPosition(pelvis_pos); + //getJoint("mPelvis")->setRotation(pelvis_rot); + //getJoint("mPelvis")->setPosition(pelvis_pos); - // Restart animations - resetAnimations(); + // Restart animations BENTO - not needed? Removing this fixes a + // problem seen if avatar is sitting and animated relative to sit + // point. + + //resetAnimations(); LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL; } -- cgit v1.2.3 From 70a38880faca24a9ed0a67606ef6bfd278ccd624 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 26 May 2016 12:50:54 -0700 Subject: Put back QuickTime plugin code for OS X only (untested - moving code to OS X dev) --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/QuickTimePlugin.cmake | 48 ++++++++++++++++++++++ indra/media_plugins/CMakeLists.txt | 6 ++- indra/newview/llappviewer.cpp | 17 +++++--- .../skins/default/xui/en/mime_types_mac.xml | 32 +++++++-------- 5 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 indra/cmake/QuickTimePlugin.cmake (limited to 'indra') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 6620dfa3cb..13a31cbce7 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -90,6 +90,7 @@ set(cmake_SOURCE_FILES Prebuilt.cmake PulseAudio.cmake Python.cmake + QuickTimePlugin.cmake TemplateCheck.cmake Tut.cmake UI.cmake diff --git a/indra/cmake/QuickTimePlugin.cmake b/indra/cmake/QuickTimePlugin.cmake new file mode 100644 index 0000000000..c08e153ee3 --- /dev/null +++ b/indra/cmake/QuickTimePlugin.cmake @@ -0,0 +1,48 @@ +# -*- cmake -*- + +if(INSTALL_PROPRIETARY) + include(Prebuilt) + if (WINDOWS) + use_prebuilt_binary(quicktime) + endif (WINDOWS) +endif(INSTALL_PROPRIETARY) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(QUICKTIME_LIBRARY QuickTime) +elseif (WINDOWS) + set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK" + CACHE PATH "Location of the QuickTime SDK.") + + find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient.lib + PATHS + ${ARCH_PREBUILT_DIRS_DEBUG} + "${QUICKTIME_SDK_DIR}\\libraries" + ) + + find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient.lib + PATHS + ${ARCH_PREBUILT_DIRS_RELEASE} + "${QUICKTIME_SDK_DIR}\\libraries" + ) + + if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) + set(QUICKTIME_LIBRARY + optimized ${RELEASE_QUICKTIME_LIBRARY} + debug ${DEBUG_QUICKTIME_LIBRARY} + ) + + endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) + + include_directories( + ${LIBS_PREBUILT_DIR}/include/quicktime + "${QUICKTIME_SDK_DIR}\\CIncludes" + ) +endif (DARWIN) + +mark_as_advanced(QUICKTIME_LIBRARY) + +if (QUICKTIME_LIBRARY) + set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.") +endif (QUICKTIME_LIBRARY) + diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 7ef29b9027..6652bd021f 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -6,11 +6,13 @@ if (LINUX) add_subdirectory(gstreamer010) endif (LINUX) -if (WINDOWS OR DARWIN) +if (DARWIN) + add_subdirectory(quicktime) add_subdirectory(cef) -endif (WINDOWS OR DARWIN) +endif (DARWIN) if (WINDOWS) + add_subdirectory(cef) add_subdirectory(winmmshim) add_subdirectory(libvlc) endif (WINDOWS) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7529254466..c2c2364c96 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -124,8 +124,10 @@ #include "llcoros.h" #if !LL_LINUX #include "cef/llceflib.h" +#if LL_WINDOWS #include "vlc/libvlc_version.h" -#endif +#endif // LL_WINDOWS +#endif // LL_LINUX // Third party library includes #include @@ -3339,7 +3341,14 @@ LLSD LLAppViewer::getViewerInfo() const info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); } -#if !LL_LINUX +#if LL_LINUX + info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION; +#else + info["LLCEFLIB_VERSION"] = "Undefined"; + +#endif + +#if LL_WINDOWS std::ostringstream ver_codec; ver_codec << LIBVLC_VERSION_MAJOR; ver_codec << "."; @@ -3347,11 +3356,7 @@ LLSD LLAppViewer::getViewerInfo() const ver_codec << "."; ver_codec << LIBVLC_VERSION_REVISION; info["LIBVLC_VERSION"] = ver_codec.str(); - - info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION; #else - info["LLCEFLIB_VERSION"] = "Undefined"; - info["LIBVLC_VERSION"] = "Undefined"; #endif diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml index e20b621cce..f71c24b2e4 100644 --- a/indra/newview/skins/default/xui/en/mime_types_mac.xml +++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml @@ -130,7 +130,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -141,7 +141,7 @@ none - media_plugin_cef + media_plugin_quicktime @@ -163,7 +163,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -174,7 +174,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -196,7 +196,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -218,7 +218,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -295,7 +295,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -306,7 +306,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -317,7 +317,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -328,7 +328,7 @@ audio - media_plugin_cef + media_plugin_quicktime @@ -438,7 +438,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -449,7 +449,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -460,7 +460,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -471,7 +471,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -482,7 +482,7 @@ movie - media_plugin_cef + media_plugin_quicktime @@ -493,7 +493,7 @@ movie - media_plugin_cef + media_plugin_quicktime -- cgit v1.2.3 From 08b8e053f49cd2cce2f3e8c6f2d4f01b04fc8fc0 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 May 2016 13:50:24 -0700 Subject: Fix typo in platform test for CEF version --- indra/newview/llappviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c2c2364c96..c8153cabda 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3341,7 +3341,7 @@ LLSD LLAppViewer::getViewerInfo() const info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); } -#if LL_LINUX +#if !LL_LINUX info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION; #else info["LLCEFLIB_VERSION"] = "Undefined"; -- cgit v1.2.3 From 8c85ec13d59e3074a1ec5559d3156d3a02d1c419 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 May 2016 13:51:22 -0700 Subject: Put back QuickTime plugin code for OS X until a LibVLC version is created --- indra/media_plugins/quicktime/CMakeLists.txt | 94 ++ .../quicktime/media_plugin_quicktime.cpp | 1082 ++++++++++++++++++++ 2 files changed, 1176 insertions(+) create mode 100755 indra/media_plugins/quicktime/CMakeLists.txt create mode 100755 indra/media_plugins/quicktime/media_plugin_quicktime.cpp (limited to 'indra') diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt new file mode 100755 index 0000000000..58391007ff --- /dev/null +++ b/indra/media_plugins/quicktime/CMakeLists.txt @@ -0,0 +1,94 @@ +# -*- cmake -*- + +project(media_plugin_quicktime) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(OpenGL) +include(QuickTimePlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(CARBON_LIBRARY Carbon) +endif (DARWIN) + + +### media_plugin_quicktime + +set(media_plugin_quicktime_SOURCE_FILES + media_plugin_quicktime.cpp + ) + +add_library(media_plugin_quicktime + SHARED + ${media_plugin_quicktime_SOURCE_FILES} +) + +target_link_libraries(media_plugin_quicktime + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${QUICKTIME_LIBRARY} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_quicktime + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_quicktime + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +endif (WINDOWS) + +if (QUICKTIME) + + add_definitions(-DLL_QUICKTIME_ENABLED=1) + + if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_quicktime + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +# We use a bunch of deprecated system APIs. + set_source_files_properties( + media_plugin_quicktime.cpp PROPERTIES + COMPILE_FLAGS -Wno-deprecated-declarations + ) + find_library(CARBON_LIBRARY Carbon) + target_link_libraries(media_plugin_quicktime ${CARBON_LIBRARY}) + endif (DARWIN) +endif (QUICKTIME) + diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp new file mode 100755 index 0000000000..ff1ed8bfbc --- /dev/null +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -0,0 +1,1082 @@ +/** + * @file media_plugin_quicktime.cpp + * @brief QuickTime plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2008&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$ + * @endcond + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + +#if defined(LL_DARWIN) +#include +#elif defined(LL_WINDOWS) +#include "llwin32headers.h" +#include "MacTypes.h" +#include "QTML.h" +#include "Movies.h" +#include "QDoffscreen.h" +#include "FixMath.h" +#include "QTLoadLibraryUtils.h" +#endif + + + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + + /* virtual */ void receiveMessage(const char *message_string); + +private: + + int mNaturalWidth; + int mNaturalHeight; + Movie mMovieHandle; + GWorldPtr mGWorldHandle; + ComponentInstance mMovieController; + int mCurVolume; + bool mMediaSizeChanging; + bool mIsLooping; + std::string mMovieTitle; + bool mReceivedTitle; + const int mMinWidth; + const int mMaxWidth; + const int mMinHeight; + const int mMaxHeight; + F64 mPlayRate; + std::string mNavigateURL; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + + // Override this to add current time and duration to the message + /*virtual*/ void setDirty(int left, int top, int right, int bottom) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + if(mMovieHandle) + { + message.setValueReal("current_time", getCurrentTime()); + message.setValueReal("duration", getDuration()); + message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); + } + + sendMessage(message); + } + + + static Rect rectFromSize(int width, int height) + { + Rect result; + + + result.left = 0; + result.top = 0; + result.right = width; + result.bottom = height; + + return result; + } + + Fixed getPlayRate(void) + { + Fixed result; + if(mPlayRate == 0.0f) + { + // Default to the movie's preferred rate + result = GetMoviePreferredRate(mMovieHandle); + if(result == 0) + { + // Don't return a 0 play rate, ever. + std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; + result = X2Fix(1.0f); + } + } + else + { + result = X2Fix(mPlayRate); + } + + return result; + } + + void load( const std::string url ) + { + + if ( url.empty() ) + return; + + // Stop and unload any existing movie before starting another one. + unload(); + + setStatus(STATUS_LOADING); + + //In case std::string::c_str() makes a copy of the url data, + //make sure there is memory to hold it before allocating memory for handle. + //if fails, NewHandleClear(...) should return NULL. + const char* url_string = url.c_str() ; + Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); + + if ( NULL == handle || noErr != MemError() || NULL == *handle ) + { + setStatus(STATUS_ERROR); + return; + } + + BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); + + OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); + DisposeHandle( handle ); + if ( noErr != err ) + { + setStatus(STATUS_ERROR); + return; + }; + + mNavigateURL = url; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message.setValue("uri", mNavigateURL); + sendMessage(message); + + // do pre-roll actions (typically fired for streaming movies but not always) + PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); + + Rect movie_rect = rectFromSize(mWidth, mHeight); + + // make a new movie controller + mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); + + // movie controller + MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); + + SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); + + // function that gets called when a frame is drawn + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); + + setStatus(STATUS_LOADED); + + sizeChanged(); + }; + + bool unload() + { + // new movie and have to get title again + mReceivedTitle = false; + + if ( mMovieHandle ) + { + StopMovie( mMovieHandle ); + if ( mMovieController ) + { + MCMovieChanged( mMovieController, mMovieHandle ); + }; + }; + + if ( mMovieController ) + { + MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); + DisposeMovieController( mMovieController ); + mMovieController = NULL; + }; + + if ( mMovieHandle ) + { + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); + DisposeMovie( mMovieHandle ); + mMovieHandle = NULL; + }; + + mGWorldHandle = NULL; + + setStatus(STATUS_NONE); + + return true; + } + + bool navigateTo( const std::string url ) + { + unload(); + load( url ); + + return true; + }; + + bool sizeChanged() + { + if ( ! mMovieHandle ) + return false; + + // Check to see whether the movie's natural size has updated + { + int width, height; + getMovieNaturalSize(&width, &height); + if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) + { + mNaturalWidth = width; + mNaturalHeight = height; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", width); + message.setValueS32("height", height); + sendMessage(message); + //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; + } + } + + + // sanitize destination size + Rect dest_rect = rectFromSize(mWidth, mHeight); + + // media depth won't change + int depth_bits = mDepth * 8; + long rowbytes = mDepth * mTextureWidth; + + if(mPixels != NULL) + { + // We have pixels. Set up a GWorld pointing at the texture. + OSErr result = QTNewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + else + { + // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. + Rect tempRect = rectFromSize(1, 1); + OSErr result = QTNewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + + SetMovieGWorld( mMovieHandle, mGWorldHandle, NULL ); + + // Set up the movie display matrix + { + // scale movie to fit rect and invert vertically to match opengl image format + MatrixRecord transform; + SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix + double scaleX = (double) mWidth / mNaturalWidth; + double scaleY = -1.0 * (double) mHeight / mNaturalHeight; + double centerX = mWidth / 2.0; + double centerY = mHeight / 2.0; + ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); + SetMovieMatrix( mMovieHandle, &transform ); + } + + // update movie controller + if ( mMovieController ) + { + MCSetControllerPort( mMovieController, mGWorldHandle ); + MCPositionController( mMovieController, &dest_rect, &dest_rect, + mcTopLeftMovie | mcPositionDontInvalidate ); + MCMovieChanged( mMovieController, mMovieHandle ); + } + + + // Emit event with size change so the calling app knows about it too + // TODO: + //LLMediaEvent event( this ); + //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); + + return true; + } + static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) + { + Boolean result = false; + + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + switch( action ) + { + // handle window resizing + case mcActionControllerSizeChanged: + // Ensure that the movie draws correctly at the new size + self->sizeChanged(); + break; + + // Block any movie controller actions that open URLs. + case mcActionLinkToURL: + case mcActionGetNextURL: + case mcActionLinkToURLExtended: + // Prevent the movie controller from handling the message + result = true; + break; + + default: + break; + }; + + return result; + }; + + static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // IMPORTANT: typically, a consumer who is observing this event will set a flag + // when this event is fired then render later. Be aware that the media stream + // can change during this period - dimensions, depth, format etc. + //LLMediaEvent event( self ); +// self->updateQuickTime(); + // TODO ^^^ + + + if ( self->mWidth > 0 && self->mHeight > 0 ) + self->setDirty( 0, 0, self->mWidth, self->mHeight ); + + return noErr; + }; + + static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // TODO: + //LLMediaEvent event( self ); + //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); + + // Send a "navigate complete" event. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message.setValue("uri", self->mNavigateURL); + message.setValueS32("result_code", 200); + message.setValue("result_string", "OK"); + self->sendMessage(message); + }; + + + void rewind() + { + GoToBeginningOfMovie( mMovieHandle ); + MCMovieChanged( mMovieController, mMovieHandle ); + }; + + bool processState() + { + if ( mCommand == COMMAND_PLAY ) + { + if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE ) + { + long state = GetMovieLoadState( mMovieHandle ); + + if ( state >= kMovieLoadStatePlaythroughOK ) + { + // if the movie is at the end (generally because it reached it naturally) + // and we play is requested, jump back to the start of the movie. + // note: this is different from having loop flag set. + if ( IsMovieDone( mMovieHandle ) ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + }; + + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + setStatus(STATUS_PLAYING); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_STOP ) + { + if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + + setStatus(STATUS_LOADED); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_PAUSE ) + { + if ( mStatus == STATUS_PLAYING ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + setStatus(STATUS_PAUSED); + mCommand = COMMAND_NONE; + }; + }; + }; + + return true; + }; + + void play(F64 rate) + { + mPlayRate = rate; + mCommand = COMMAND_PLAY; + }; + + void stop() + { + mCommand = COMMAND_STOP; + }; + + void pause() + { + mCommand = COMMAND_PAUSE; + }; + + void getMovieNaturalSize(int *movie_width, int *movie_height) + { + Rect rect; + + GetMovieNaturalBoundsRect( mMovieHandle, &rect ); + + int width = ( rect.right - rect.left ); + int height = ( rect.bottom - rect.top ); + + // make sure width and height fall in valid range + if ( width < mMinWidth ) + width = mMinWidth; + + if ( width > mMaxWidth ) + width = mMaxWidth; + + if ( height < mMinHeight ) + height = mMinHeight; + + if ( height > mMaxHeight ) + height = mMaxHeight; + + // return the new rect + *movie_width = width; + *movie_height = height; + } + + void updateQuickTime(int milliseconds) + { + if ( ! mMovieHandle ) + return; + + if ( ! mMovieController ) + return; + + // this wasn't required in 1.xx viewer but we have to manually + // work the Windows message pump now + #if defined( LL_WINDOWS ) + MSG msg; + while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) + { + GetMessage( &msg, NULL, 0, 0 ); + TranslateMessage( &msg ); + DispatchMessage( &msg ); + }; + #endif + + MCIdle( mMovieController ); + + if ( ! mGWorldHandle ) + return; + + if ( mMediaSizeChanging ) + return; + + // update state machine + processState(); + + // see if title arrived and if so, update member variable with contents + checkTitle(); + + // QT call to see if we are at the end - can't do with controller + if ( IsMovieDone( mMovieHandle ) ) + { + // special code for looping - need to rewind at the end of the movie + if ( mIsLooping ) + { + // go back to start + rewind(); + + if ( mMovieController ) + { + // kick off new play + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + + // set the volume + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + } + else + { + if(mStatus == STATUS_PLAYING) + { + setStatus(STATUS_DONE); + } + } + } + + }; + + void seek( F64 time ) + { + if ( mMovieController ) + { + TimeRecord when; + when.scale = GetMovieTimeScale( mMovieHandle ); + when.base = 0; + + // 'time' is in (floating point) seconds. The timebase time will be in 'units', where + // there are 'scale' units per second. + SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); + + when.value.hi = ( SInt32 )( raw_time >> 32 ); + when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); + + MCDoAction( mMovieController, mcActionGoToTime, &when ); + }; + }; + + F64 getLoadedDuration() + { + TimeValue duration; + if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) + { + // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. + duration = GetMovieDuration( mMovieHandle ); + } + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getDuration() + { + TimeValue duration = GetMovieDuration( mMovieHandle ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getCurrentTime() + { + TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)curr_time / (F64)scale; + }; + + void setVolume( F64 volume ) + { + mCurVolume = (short)(volume * ( double ) 0x100 ); + + if ( mMovieController ) + { + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update(int milliseconds = 0) + { + updateQuickTime(milliseconds); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // Grab movie title into mMovieTitle - should be called repeatedly + // until it returns true since movie title takes a while to become + // available. + const bool getMovieTitle() + { + // grab meta data from movie + QTMetaDataRef media_data_ref; + OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref ); + if ( noErr != result ) + return false; + + // look up "Display Name" in meta data + OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; + QTMetaDataItem item = kQTMetaDataItemUninitialized; + result = (OSErr)QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, + 0, kQTMetaDataKeyFormatCommon, + (const UInt8 *)&meta_data_key, + sizeof( meta_data_key ), &item ); + if ( noErr != result ) + return false; + + // find the size of the title + ByteCount size; + result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); + if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ ) + return false; + + // allocate some space and grab it + UInt8* item_data = new UInt8[ size + 1 ]; + memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) ); + result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); + if ( noErr != result ) + { + delete [] item_data; + return false; + }; + + // save it + if ( strlen( (char*)item_data ) ) + mMovieTitle = std::string( (char* )item_data ); + else + mMovieTitle = ""; + + // clean up + delete [] item_data; + + return true; + }; + + // called regularly to see if title changed + void checkTitle() + { + // we did already receive title so keep checking + if ( ! mReceivedTitle ) + { + // grab title from movie meta data + if ( getMovieTitle() ) + { + // pass back to host application + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", mMovieTitle ); + sendMessage( message ); + + // stop looking once we find a title for this movie. + // TODO: this may to be reset if movie title changes + // during playback but this is okay for now + mReceivedTitle = true; + }; + }; + }; +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mMinWidth( 0 ), + mMaxWidth( 2048 ), + mMinHeight( 0 ), + mMaxHeight( 2048 ) +{ +// std::cerr << "MediaPluginQuickTime constructor" << std::endl; + + mNaturalWidth = -1; + mNaturalHeight = -1; + mMovieHandle = 0; + mGWorldHandle = 0; + mMovieController = 0; + mCurVolume = 0x99; + mMediaSizeChanging = false; + mIsLooping = false; + mMovieTitle = std::string(); + mReceivedTitle = false; + mCommand = COMMAND_NONE; + mPlayRate = 0.0f; + mStatus = STATUS_NONE; +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ +// std::cerr << "MediaPluginQuickTime destructor" << std::endl; + + ExitMovies(); + +#ifdef LL_WINDOWS + TerminateQTML(); +// std::cerr << "QuickTime closing down" << std::endl; +#endif +} + + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ +// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + #ifdef LL_WINDOWS + + // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime + // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html + // The solution presented there appears to work. + QTLoadLibrary("qtcf.dll"); + + // main initialization for QuickTime - only required on Windows + OSErr result = InitializeQTML( 0L ); + if ( result != noErr ) + { + //TODO: If no QT on Windows, this fails - respond accordingly. + } + else + { + //std::cerr << "QuickTime initialized" << std::endl; + }; + #endif + + // required for both Windows and Mac + EnterMovies(); + + std::string plugin_version = "QuickTime media plugin, QuickTime version "; + + long version = 0; + Gestalt( gestaltQuickTimeVersion, &version ); + std::ostringstream codec( "" ); + codec << std::hex << version << std::dec; + plugin_version += codec.str(); + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + // TODO: clean up here + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name +// << ", size: " << info.mSize +// << ", address: " << info.mAddress +// << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie GWorld is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // This is the media init message -- all necessary data for initialization should have been received. + + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + #if defined(LL_WINDOWS) + // Values for Windows + mDepth = 3; + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + + // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. + // Padding to a multiple of 3*32 guarantees it'll divide out properly. + message.setValueU32("padding", 32 * 3); + #else + // Values for Mac + mDepth = 4; + message.setValueU32("format", GL_BGRA_EXT); + #ifdef __BIG_ENDIAN__ + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); + #else + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); + #endif + + // Pad texture width to a multiple of 32 bytes, to line up with cache lines. + message.setValueU32("padding", 32); + #endif + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { +// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; +// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + mMediaSizeChanging = false; + + sizeChanged(); + + update(); + }; + }; + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + load( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + F64 rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + F64 time = message_in.getValueReal("time"); + seek(time); + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); + *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + +#else // LL_QUICKTIME_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ + // no-op +} + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without quicktime enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_QUICKTIME_ENABLED -- cgit v1.2.3 From ccfb18948df97bbb671fdd925b9d7a84e6345339 Mon Sep 17 00:00:00 2001 From: Nicky Date: Fri, 27 May 2016 00:27:10 +0200 Subject: - Make popup appear on the right screen coordinates (this was broken after the flipy switch) - Make sure the popup stays until it is dismissed (no need to hold the mouse button to scroll through eg a listbox) [This needs a CEF change.) --- indra/media_plugins/cef/media_plugin_cef.cpp | 58 +++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index d61bd680df..84fe83408f 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -100,6 +100,12 @@ private: LLCEFLib* mLLCEFLib; VolumeCatcher mVolumeCatcher; + + U8 *mPopupBuffer; + U32 mPopupW; + U32 mPopupH; + U32 mPopupX; + U32 mPopupY; }; //////////////////////////////////////////////////////////////////////////////// @@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data) mCookiePath = ""; mPickedFile = ""; mLLCEFLib = new LLCEFLib(); + + mPopupBuffer = NULL; + mPopupW = 0; + mPopupH = 0; + mPopupX = 0; + mPopupY = 0; } //////////////////////////////////////////////////////////////////////////////// // MediaPluginCEF::~MediaPluginCEF() { + delete[] mPopupBuffer; } //////////////////////////////////////////////////////////////////////////////// @@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg) // void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup) { - if (mPixels && pixels) + if( is_popup ) + { + delete mPopupBuffer; + mPopupBuffer = NULL; + mPopupH = 0; + mPopupW = 0; + mPopupX = 0; + mPopupY = 0; + } + + if( mPixels && pixels ) { if (is_popup) { - for (int line = 0; line < height; ++line) + if( width > 0 && height> 0 ) { - int inverted_y = mHeight - y - height; - int src = line * width * mDepth; - int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth; - - if (dst + width * mDepth < mWidth * mHeight * mDepth) - { - memcpy(mPixels + dst, pixels + src, width * mDepth); - } + mPopupBuffer = new U8[ width * height * mDepth ]; + memcpy( mPopupBuffer, pixels, width * height * mDepth ); + mPopupH = height; + mPopupW = width; + mPopupX = x; + mPopupY = y; } } else @@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, { memcpy(mPixels, pixels, mWidth * mHeight * mDepth); } + if( mPopupBuffer && mPopupH && mPopupW ) + { + U32 bufferSize = mWidth * mHeight * mDepth; + U32 popupStride = mPopupW * mDepth; + U32 bufferStride = mWidth * mDepth; + int dstY = mPopupY; + + int src = 0; + int dst = dstY * mWidth * mDepth + mPopupX * mDepth; + + for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line ) + { + memcpy( mPixels + dst, mPopupBuffer + src, popupStride ); + src += popupStride; + dst += bufferStride; + } + } } setDirty(0, 0, mWidth, mHeight); -- cgit v1.2.3 From 282956e7688169e539059385962cbd6a295255f6 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 27 May 2016 16:53:16 -0700 Subject: Some simple tidy up and added a proper URL for video test button in web content floater --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 14 +++----------- .../skins/default/textures/icons/Video_URL_Off.png | Bin 0 -> 282 bytes indra/newview/skins/default/textures/textures.xml | 5 ++++- 3 files changed, 7 insertions(+), 12 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/Video_URL_Off.png (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 92bfc15113..43d4e95243 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -173,26 +173,18 @@ void MediaPluginLibVLC::playMedia() gLibVLCMedia = libvlc_media_new_location(gLibVLC, mURL.c_str()); if (!gLibVLCMedia) { - printf("libvlc_media_new_location failed\n"); - } - else - { - printf("libvlc_media_new_location ok\n"); + gLibVLCMediaPlayer = 0; + return; } gLibVLCMediaPlayer = libvlc_media_player_new_from_media(gLibVLCMedia); if (!gLibVLCMediaPlayer) { - printf("libvlc_media_player_new_from_media failed\n"); - } - else - { - printf("libvlc_media_player_new_from_media ok...\n"); + return; } libvlc_media_release(gLibVLCMedia); - gVLCCallbackContext.parent = this; gVLCCallbackContext.texture_pixels = mPixels; gVLCCallbackContext.mp = gLibVLCMediaPlayer; diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.png new file mode 100644 index 0000000000..40e5df7d81 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Video_URL_Off.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72037a84b3..01e8c16937 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -676,7 +676,10 @@ with the same filename but different name - + + + + -- cgit v1.2.3 From 85d92553d882b014dc1605198555f683191a8ae5 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 31 May 2016 17:32:05 +0300 Subject: MAINT-6447 In OS X El Capitan, display by a Gothic font is needed. --- indra/newview/skins/default/xui/en/fonts.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 5d05ecf127..550af03683 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -10,6 +10,7 @@ ArialUni.ttf + ヒラギノ角ゴシック W3.ttc ヒラギノ角ゴ Pro W3.otf ヒラギノ角ゴ ProN W3.otf ãƒ’ãƒ©ã‚­ã‚™ãƒŽæ˜Žæœ ProN W3.ttc -- cgit v1.2.3 From dca6153c236dbd81f3f0c23b449136452f7d7ef9 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 31 May 2016 09:41:37 -0700 Subject: Remove local flip (as part of resize) in QuickTime plugin for OSX --- indra/media_plugins/quicktime/media_plugin_quicktime.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index ff1ed8bfbc..011fd4e051 100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -311,7 +311,9 @@ private: MatrixRecord transform; SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix double scaleX = (double) mWidth / mNaturalWidth; - double scaleY = -1.0 * (double) mHeight / mNaturalHeight; + + // 2016-05-31 CP remove local flip (via -1.0) since texture coods for media on a prim are now flipped for VLC/CEF + double scaleY = 1.0 * (double) mHeight / mNaturalHeight; double centerX = mWidth / 2.0; double centerY = mHeight / 2.0; ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); -- cgit v1.2.3 From 69174fcc58e0a2e67a417c2e0060d9f36a0ba238 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 31 May 2016 14:51:40 -0700 Subject: Fix windows line endings --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 78 +++++++++++----------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 43d4e95243..3852d10c44 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -330,45 +330,45 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) playMedia(); } } - else - if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if (message_name == "stop") - { - if (gLibVLCMediaPlayer) - { - libvlc_media_player_stop(gLibVLCMediaPlayer); - } - } - else if (message_name == "start") - { - if (gLibVLCMediaPlayer) - { - libvlc_media_player_play(gLibVLCMediaPlayer); - } - } - else if (message_name == "pause") - { - if (gLibVLCMediaPlayer) - { - libvlc_media_player_pause(gLibVLCMediaPlayer); - } - } - else if (message_name == "seek") - { - } - else if (message_name == "set_loop") - { - } - else if (message_name == "set_volume") - { - if (gLibVLCMediaPlayer) - { - F64 volume = message_in.getValueReal("volume"); - libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); - } - } - } + else + if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if (message_name == "stop") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_stop(gLibVLCMediaPlayer); + } + } + else if (message_name == "start") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_play(gLibVLCMediaPlayer); + } + } + else if (message_name == "pause") + { + if (gLibVLCMediaPlayer) + { + libvlc_media_player_pause(gLibVLCMediaPlayer); + } + } + else if (message_name == "seek") + { + } + else if (message_name == "set_loop") + { + } + else if (message_name == "set_volume") + { + if (gLibVLCMediaPlayer) + { + F64 volume = message_in.getValueReal("volume"); + libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); + } + } + } } } -- cgit v1.2.3 From b61d62bbf405774c3fa51a490e6d13c4288a567c Mon Sep 17 00:00:00 2001 From: Nicky Date: Wed, 1 Jun 2016 22:29:27 +0200 Subject: GCC compile fix (function returns a pointer, not a bool). --- indra/llui/llview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 8f7cac1f61..bbc55b785c 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -807,7 +807,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) LLView* LLView::childFromPoint(S32 x, S32 y, bool recur) { if (!getVisible()) - return false; + return NULL; BOOST_FOREACH(LLView* viewp, mChildList) { -- cgit v1.2.3 From 254fbd69a65ccbdfbf3678f1f99bda292b4cfc59 Mon Sep 17 00:00:00 2001 From: Nicky Date: Wed, 1 Jun 2016 22:30:12 +0200 Subject: GCC compile fix, array initialization needs proper type. --- indra/newview/llsurfacepatch.cpp | 4 ++-- indra/newview/llworld.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 2d06b8599c..d28a7cc048 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f); F32 vec[3] = { - fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), - fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), + (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), + (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), 0.f }; F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 11d3706821..cee47a591e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects() center_y = min_y + (wy >> 1); S32 add_boundary[4] = { - 512 - (max_x - region_x), - 512 - (max_y - region_y), - 512 - (region_x - min_x), - 512 - (region_y - min_y) }; + (S32)(512 - (max_x - region_x)), + (S32)(512 - (max_y - region_y)), + (S32)(512 - (region_x - min_x)), + (S32)(512 - (region_y - min_y)) }; S32 dir; for (dir = 0; dir < 8; dir++) -- cgit v1.2.3 From b78f19f82e94f3fb8c5717bc36656856840f3807 Mon Sep 17 00:00:00 2001 From: Nicky Date: Wed, 1 Jun 2016 22:31:00 +0200 Subject: Linux: SDL has a dependency on X11 -> Link against it. --- indra/cmake/LLWindow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index ba07a80f05..80af7ff2ab 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -18,7 +18,7 @@ else (USESYSTEMLIBS) use_prebuilt_binary(SDL) set (SDL_FOUND TRUE) set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) - set (SDL_LIBRARY SDL directfb fusion direct) + set (SDL_LIBRARY SDL directfb fusion direct X11) endif (LINUX) endif (USESYSTEMLIBS) -- cgit v1.2.3 From bebfe34aac9b217a807baea8fc78ab20c0c94045 Mon Sep 17 00:00:00 2001 From: Nicky Date: Wed, 1 Jun 2016 22:33:30 +0200 Subject: Linux: Use media_plugin_libvlc for media playback. --- indra/cmake/LibVLCPlugin.cmake | 5 ++++ indra/media_plugins/CMakeLists.txt | 1 + indra/newview/CMakeLists.txt | 1 + .../skins/default/xui/en/mime_types_linux.xml | 30 +++++++++++----------- indra/newview/viewer_manifest.py | 12 ++++++++- 5 files changed, 33 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake index 0d2c46bac0..4472676fb4 100644 --- a/indra/cmake/LibVLCPlugin.cmake +++ b/indra/cmake/LibVLCPlugin.cmake @@ -19,4 +19,9 @@ if (WINDOWS) ) elseif (DARWIN) elseif (LINUX) + # Specify a full path to make sure we get a static link + set(VLC_PLUGIN_LIBRARIES + ${LIBS_PREBUILT_DIR}/lib/libvlc.a + ${LIBS_PREBUILT_DIR}/lib/libvlccore.a + ) endif (WINDOWS) diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 6652bd021f..9055e0111a 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(base) if (LINUX) add_subdirectory(gstreamer010) + add_subdirectory(libvlc) endif (LINUX) if (DARWIN) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9ffc99adb2..f7f01a6e4e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1969,6 +1969,7 @@ if (LINUX) linux-crash-logger SLPlugin media_plugin_gstreamer010 + media_plugin_libvlc llcommon ) diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml index 84aeaf3b54..7188b1e699 100644 --- a/indra/newview/skins/default/xui/en/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -130,7 +130,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -163,7 +163,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -174,7 +174,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -196,7 +196,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -218,7 +218,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -295,7 +295,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -306,7 +306,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -317,7 +317,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -328,7 +328,7 @@ audio - media_plugin_gstreamer + media_plugin_libvlc @@ -438,7 +438,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -449,7 +449,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -460,7 +460,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -471,7 +471,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -482,7 +482,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc @@ -493,7 +493,7 @@ movie - media_plugin_gstreamer + media_plugin_libvlc diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e7f517518b..04cc4774e4 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1092,8 +1092,18 @@ class LinuxManifest(ViewerManifest): # plugins if self.prefix(src="", dst="bin/llplugin"): self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so") self.end_prefix("bin/llplugin") + if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): + self.path( "plugins.dat" ) + self.path( "*/*.so" ) + self.end_prefix() + + if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"): + self.path( "libvlc*.so*" ) + self.end_prefix() + # llcommon if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"): print "Skipping llcommon.so (assuming llcommon was linked statically)" @@ -1147,7 +1157,7 @@ class LinuxManifest(ViewerManifest): def strip_binaries(self): if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure class Linux_i686_Manifest(LinuxManifest): def construct(self): -- cgit v1.2.3 From 66e8ed280707b2ada96708bb97f472280bf9431e Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 1 Jun 2016 14:41:13 -0700 Subject: Point audio MIME types at libVLC media plugin vs CEF --- indra/newview/skins/default/xui/en/mime_types.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 2867204318..c27fac6731 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -174,7 +174,7 @@ audio - media_plugin_cef + media_plugin_libvlc @@ -317,7 +317,7 @@ audio - media_plugin_cef + media_plugin_libvlc @@ -328,7 +328,7 @@ audio - media_plugin_cef + media_plugin_libvlc @@ -339,7 +339,7 @@ audio - media_plugin_cef + media_plugin_libvlc -- cgit v1.2.3 From 956c412aa431ccee80b7b9c8f0e224d5246af1f1 Mon Sep 17 00:00:00 2001 From: ruslantproductengine Date: Thu, 2 Jun 2016 15:09:09 +0300 Subject: MAINT-5207 Build: Snap to grid / Grid options broken, object snaps to incorrect Units FIXED - Decrase the minimal dev. pix. width to 3. That should be enought. - Remove the mouse down offset from the snapping algorithm. IMHO it shouldn't be here. Snapping should be right on the mosue pointer. --- indra/newview/llmanip.h | 4 ++-- indra/newview/llmaniptranslate.cpp | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 1fb05e047a..69881e8589 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -1,4 +1,4 @@ -/** +/** * @file llmanip.h * @brief LLManip class definition * @@ -37,7 +37,7 @@ class LLToolComposite; class LLVector3; class LLObjectSelection; -const S32 MIN_DIVISION_PIXEL_WIDTH = 9; +const S32 MIN_DIVISION_PIXEL_WIDTH = 3; class LLManip : public LLTool { diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b4259a456c..3975d3980b 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llmaniptranslate.cpp * @brief LLManipTranslate class implementation * @@ -548,12 +548,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) if (off_axis_magnitude > mSnapOffsetMeters) { mInSnapRegime = TRUE; - LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal); LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); - if (!gSavedSettings.getBOOL("SnapToMouseCursor")) - { - cursor_snap_agent -= mouse_down_offset; - } F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; -- cgit v1.2.3 From 4796f717c2a2c5756b91fa5281019ff23a10a613 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 2 Jun 2016 09:49:08 -0700 Subject: BUG-18252 - media flipped on OS X when played in 2D browser --- indra/media_plugins/quicktime/media_plugin_quicktime.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 011fd4e051..6d4c6ca43d 100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -921,7 +921,10 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) #endif message.setValueS32("depth", mDepth); message.setValueU32("internalformat", GL_RGB); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + + // note this apparently only has an effect when media is opened in 2D browser. + // see https://jira.secondlife.com/browse/BUG-18252 - media flipped in 2D so flipping it back. + message.setValueBoolean("coords_opengl", false); // true == use OpenGL-style coordinates, false == (0,0) is upper left. message.setValueBoolean("allow_downsample", true); sendMessage(message); } -- cgit v1.2.3 From 75ebd835730f85aebd4b2a6238638e6cae4f435d Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 2 Jun 2016 19:59:35 +0300 Subject: MAINT-6448 PERMISSION_DEBIT notification should default to Deny --- indra/newview/lltoastscriptquestion.cpp | 19 +++++++++++++++++++ indra/newview/lltoastscriptquestion.h | 2 ++ 2 files changed, 21 insertions(+) (limited to 'indra') diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index 91ba8c0247..7a3a1d8fd7 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -54,6 +54,19 @@ BOOL LLToastScriptQuestion::postBuild() return TRUE; } + +// virtual +void LLToastScriptQuestion::setFocus(BOOL b) +{ + LLToastPanel::setFocus(b); + // toast can fade out and disappear with focus ON, so reset to default anyway + LLButton* dfbutton = getDefaultButton(); + if (dfbutton && dfbutton->getVisible() && dfbutton->getEnabled()) + { + dfbutton->setFocus(b); + } +} + void LLToastScriptQuestion::snapToMessageHeight() { LLTextBox* mMessage = getChild("top_info_message"); @@ -118,6 +131,12 @@ void LLToastScriptQuestion::createButtons() button->setRect(rect); buttons_width += rect.getWidth() + LEFT_PAD; + + if (form_element.has("default") && form_element["default"].asBoolean()) + { + button->setFocus(TRUE); + setDefaultBtn(button); + } } } } diff --git a/indra/newview/lltoastscriptquestion.h b/indra/newview/lltoastscriptquestion.h index 3a557f60f6..a756f88415 100644 --- a/indra/newview/lltoastscriptquestion.h +++ b/indra/newview/lltoastscriptquestion.h @@ -39,6 +39,8 @@ public: virtual BOOL postBuild(); virtual ~LLToastScriptQuestion(){}; + /*virtual*/ void setFocus(BOOL b); + private: void snapToMessageHeight(); -- cgit v1.2.3 From 487f858c5e70b3ee510380f59de7a54c8502c983 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 2 Jun 2016 17:48:03 -0400 Subject: SL-390 correct spelling of "tongue" --- indra/newview/character/avatar_lad.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index aab393c480..23c5352015 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -582,7 +582,7 @@ pie_slice="11" name="Tongue" joint="mFaceTongueTip" - location="ATTACH_FACE_TOUNGE" + location="ATTACH_FACE_TONGUE" position="0.000 0.000 0.000" rotation="0 0 0" visible_in_first_person="true"/> -- cgit v1.2.3 From e46ac9d1440da85238599fb11e1da1ae0386b428 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 2 Jun 2016 17:48:58 -0400 Subject: synchronize default lsl hints with authoritative server version (not required, but does not hurt) --- .../newview/app_settings/keywords_lsl_default.xml | 477 ++++++++++++++++----- 1 file changed, 360 insertions(+), 117 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/keywords_lsl_default.xml b/indra/newview/app_settings/keywords_lsl_default.xml index ddd287faf4..bb23ec04dc 100644 --- a/indra/newview/app_settings/keywords_lsl_default.xml +++ b/indra/newview/app_settings/keywords_lsl_default.xml @@ -528,7 +528,7 @@ type integer value - 27 + 26 tooltip Attach to the avatar's lower upper leg. @@ -678,6 +678,141 @@ tooltip Attach to the avatar's right upper leg. + ATTACH_LHAND_RING1 + + type + integer + value + 41 + tooltip + Attach to the avatar's left ring finger. + + ATTACH_RHAND_RING1 + + type + integer + value + 42 + tooltip + Attach to the avatar's right ring finger. + + ATTACH_TAIL_BASE + + type + integer + value + 43 + tooltip + Attach to the avatar's tail base. + + ATTACH_TAIL_TIP + + type + integer + value + 44 + tooltip + Attach to the avatar's tail tip. + + ATTACH_LWING + + type + integer + value + 45 + tooltip + Attach to the avatar's left wing. + + ATTACH_RWING + + type + integer + value + 46 + tooltip + Attach to the avatar's right wing. + + ATTACH_FACE_JAW + + type + integer + value + 47 + tooltip + Attach to the avatar's jaw. + + ATTACH_FACE_LEAR + + type + integer + value + 48 + tooltip + Attach to the avatar's left ear (extended). + + ATTACH_FACE_REAR + + type + integer + value + 49 + tooltip + Attach to the avatar's right ear (extended). + + ATTACH_FACE_LEYE + + type + integer + value + 50 + tooltip + Attach to the avatar's left eye (extended). + + ATTACH_FACE_REYE + + type + integer + value + 51 + tooltip + Attach to the avatar's right eye (extended). + + ATTACH_FACE_TONGUE + + type + integer + value + 52 + tooltip + Attach to the avatar's tongue. + + ATTACH_GROIN + + type + integer + value + 53 + tooltip + Attach to the avatar's groin. + + ATTACH_HIND_LFOOT + + type + integer + value + 54 + tooltip + Attach to the avatar's left hind foot. + + ATTACH_HIND_RFOOT + + type + integer + value + 55 + tooltip + Attach to the avatar's right hind foot. + AVOID_CHARACTERS type @@ -809,7 +944,7 @@ type integer value - 6 + 5 tooltip @@ -818,7 +953,7 @@ type integer value - 22 + 21 tooltip @@ -872,7 +1007,7 @@ type integer value - 2048 + 0x800 tooltip @@ -1463,9 +1598,9 @@ type float value - 0.01745329 + 0.017453293 tooltip - 0.01745329 - Number of radians per degree. + 0.017453293 - Number of radians per degree. You can use this to convert degrees to radians by multiplying the degrees by this number. DENSITY @@ -2299,7 +2434,7 @@ NULL_KEY type - key + string value 00000000-0000-0000-0000-000000000000 tooltip @@ -2395,6 +2530,15 @@ tooltip Gets the object's name. + OBJECT_OMEGA + + type + integer + value + 29 + tooltip + Gets an object's angular velocity. + OBJECT_OWNER type @@ -2404,6 +2548,15 @@ tooltip Gets an object's owner's key. If id is group owned, a NULL_KEY is returned. + OBJECT_PRIM_COUNT + + type + integer + value + 30 + tooltip + Gets the prim count of the object. The script and target object must be owned by the same owner + OBJECT_PATHFINDING_TYPE type @@ -2494,6 +2647,15 @@ tooltip + OBJECT_REZZER_KEY + + type + integer + value + 32 + tooltip + + OBJECT_ROOT type @@ -2566,6 +2728,15 @@ tooltip Returns boolean, detailing if temporary is enabled or disabled on the object. + OBJECT_TOTAL_INVENTORY_COUNT + + type + integer + value + 31 + tooltip + Gets the total inventory count of the object. The script and target object must be owned by the same owner + OBJECT_TOTAL_SCRIPT_COUNT type @@ -3052,6 +3223,33 @@ tooltip + PASS_ALWAYS + + type + integer + value + 1 + tooltip + Always pass the event. + + PASS_NEVER + + type + integer + value + 2 + tooltip + Always pass the event. + + PASS_IF_NOT_HANDLED + + type + integer + value + 0 + tooltip + Pass the event if there is no script handling the event in the prim. + PASSIVE type @@ -4387,6 +4585,24 @@ tooltip + PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR + + type + integer + value + 5 + tooltip + + + PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA + + type + integer + value + 9 + tooltip + + PSYS_PART_BF_SOURCE_ALPHA type @@ -4536,7 +4752,7 @@ type integer value - 19 + 7 tooltip Age in seconds of a particle at which it dies. @@ -5061,7 +5277,7 @@ type integer value - 2 + 0 tooltip @@ -5295,7 +5511,7 @@ type integer value - 64 + 0x40 tooltip Controls whether the object can be grabbed.\nA grab is the default action when in third person, and is available as the hand tool in build mode. This is useful for physical objects that you don't want other people to be able to trivially disturb. The default is FALSE @@ -5304,7 +5520,7 @@ type integer value - 1024 + 0x400 tooltip Prevent click-and-drag movement on all prims in the object. @@ -5500,7 +5716,7 @@ TEXTURE_BLANK type - key + string value 5748decc-f629-461c-9a36-a35a221fe21f tooltip @@ -5509,7 +5725,7 @@ TEXTURE_DEFAULT type - key + string value 89556747-24cb-43ed-920b-47caed15465f tooltip @@ -5518,7 +5734,7 @@ TEXTURE_MEDIA type - key + string value 8b5fec65-8d8d-9dc5-cda8-8fdf2716e361 tooltip @@ -5527,7 +5743,7 @@ TEXTURE_PLYWOOD type - key + string value 89556747-24cb-43ed-920b-47caed15465f tooltip @@ -5536,7 +5752,7 @@ TEXTURE_TRANSPARENT type - key + string value 8dcd4a48-2d37-4909-9f78-f7a9eb4ef903 tooltip @@ -5956,7 +6172,7 @@ type integer value - 35 + 31 tooltip The timescale for exponential decay of the linear motors magnitude. @@ -6204,15 +6420,6 @@ tooltip An attempted write data to the key-value store failed due to the data quota being met. - LSL_XP_ERROR_REQUEST_PERM_TIMEOUT - - type - integer - value - 18 - tooltip - The request for experience permissions was ignored and timed out. - XP_ERROR_RETRY_UPDATE type @@ -6562,30 +6769,43 @@ experience_permissions arguments - - agent_id - + + + agent_id + type key tooltip ID of the agent approving permission for the Experience. - - + + + experience_permissions_denied arguments - - agent_id - + + + agent_id + type key tooltip ID of the agent denying permission for the Experience. - - + + + + Reason + + type + integer + tooltip + One of the XP_ERROR_... constants describing the reason why the Experience permissions were denied for the agent. + + + tooltip - One of the XP_ERROR_... constants describing the reason why the Experience permissions were denied for the agent. + Describes why the Experience permissions were denied for the agent. http_request @@ -7281,15 +7501,17 @@ return integer arguments - - AgentID - + + + AgentID + type key tooltip - - + + + tooltip Returns TRUE if the agent is in the Experience and the Experience can run in the current location. @@ -8035,7 +8257,8 @@ return key arguments - + + Key type @@ -8043,6 +8266,8 @@ tooltip + + Value type @@ -8050,7 +8275,8 @@ tooltip - + + tooltip Starts an asychronous transaction to create a key-value pair. Will fail with XP_ERROR_STORAGE_EXCEPTION if the key already exists. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value passed to the function. @@ -8148,15 +8374,17 @@ return key arguments - - Key - + + + Key + type string tooltip - - + + + tooltip Starts an asychronous transaction to delete a key-value pair. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key. @@ -9549,15 +9777,17 @@ return list arguments - - ExperienceID - + + + ExperienceID + type key tooltip May be NULL_KEY to retrieve the details for the script's Experience - - + + + tooltip Returns a list with the following Experience properties: [Experience Name, Owner ID, Group ID, Experience ID, State, State Message]. State is an integer corresponding to one of the constants XP_ERROR_... and State Message is the string returned by llGetExperienceErrorMessage for that integer. @@ -10782,7 +11012,7 @@ sleep 0.0 return - void + float arguments tooltip @@ -11390,7 +11620,7 @@ sleep 0.0 return - void + integer arguments @@ -11937,22 +12167,26 @@ return key arguments - - First - + + + First + type string tooltip Index of the first key to return. - - Count - + + + + Count + type string tooltip The number of keys to return. - - + + + tooltip Starts an asychronous transaction the request a number of keys from the data store. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. The error XP_ERROR_KEY_NOT_FOUND is returned if First is greater than or equal to the number of keys in the data store. In the success case the subsequent items will be the keys requested. The number of keys returned may be less than requested if the return value is too large or if there is not enough keys remaining. The order keys are returned is not guaranteed but is stable between subsequent calls as long as no keys are added or removed. Because the keys are returned in a comma-delimited list it is not recommended to use commas in key names if this function is used. @@ -11981,7 +12215,7 @@ Rules type - integer + list tooltip Particle system rules list in the format [ rule1, data1, rule2, data2 . . . ruleN, dataN ] @@ -13141,6 +13375,15 @@ + + Bounce + + type + integer + tooltip + + + Texture @@ -13159,6 +13402,15 @@ + + Bounce_Offset + + type + float + tooltip + + + tooltip Make a fountain of particles. Deprecated: Use llParticleSystem instead.\nMake a fountain of particles using texture from the objects inventory. Deprecated: Use llParticleSystem instead. @@ -13959,7 +14211,7 @@ sleep 0.0 return - void + float arguments @@ -14098,7 +14350,8 @@ return key arguments - + + Key type @@ -14106,7 +14359,8 @@ tooltip - + + tooltip Starts an asychronous transaction to retrieve the value associated with the key given. Will fail with XP_ERROR_KEY_NOT_FOUND if the key does not exist. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key. @@ -14148,7 +14402,7 @@ Text type - integer + string tooltip Message to be transmitted. @@ -14541,22 +14795,26 @@ return void arguments - - AvatarID - + + + AvatarID + type key tooltip - - unused - + + + + unused + type string tooltip Not used, should be "" - - + + + tooltip Ask the agent for permission to participate in an experience. This request is similar to llRequestPermissions with the following permissions: PERMISSION_TAKE_CONTROLS, PERMISSION_TRIGGER_ANIMATION, PERMISSION_ATTACH, PERMISSION_TRACK_CAMERA, PERMISSION_CONTROL_CAMERA and PERMISSION_TELEPORT. However, unlike llRequestPermissions the decision to allow or block the request is persistent and applies to all scripts using the experience grid wide. Subsequent calls to llRequestExperiencePermissions from scripts in the experience will receive the same response automatically with no user interaction. One of experience_permissions or experience_permissions_denied will be generated in response to this call. Outstanding permission requests will be lost if the script is derezzed, moved to another region or reset. @@ -17363,7 +17621,7 @@ ParameterValue type - float + rotation tooltip @@ -17418,7 +17676,7 @@ ParameterValue type - float + vector tooltip @@ -18487,36 +18745,44 @@ return key arguments - - Key - + + + Key + type string tooltip - - Value - + + + + Value + type string tooltip - - Checked - + + + + Checked + type integer tooltip - - OriginalValue - + + + + OriginalValue + type string tooltip - - + + + tooltip Starts an asychronous transaction to update the value associated with the key given. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key. If Checked is 1 the existing value in the data store must match the OriginalValue passed or XP_ERROR_RETRY_UPDATE will be returned. If Checked is 0 the key will be created if necessary. @@ -18868,31 +19134,8 @@ tooltip Returns the largest multiplicative uniform scale factor that can be successfully applied (via llScaleByFactor()) to the object without violating prim size or linkability rules. - llScaleByFactor - - energy - 10.0 - sleep - 0.0 - return - float - arguments - - - Factor - - type - float - tooltip - - - - - tooltip - Tries to uniformly scale the object by a multiplicative factor. Returns TRUE on success or FALSE on failure. - llsd-lsl-syntax-version - 2 + 2 -- cgit v1.2.3 From 53cc5ba2256af3f70fc9aa69e06a1db0e195079b Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 2 Jun 2016 18:24:15 -0700 Subject: FIX MAINT-6748 content looks correct but page links are flipped vertically --- indra/media_plugins/cef/media_plugin_cef.cpp | 2 ++ indra/newview/llmediactrl.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 84fe83408f..be16ff7946 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -597,6 +597,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); + y = mHeight - y; + // only even send left mouse button events to LLCEFLib // (partially prompted by crash in OS X CEF when sending right button events) // we catch the right click in viewer and display our own context menu anyway diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 9cf3249983..08c927483f 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -911,7 +911,7 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) } x = ll_round((F32)x * LLUI::getScaleFactor().mV[VX]); - if ( ! coords_opengl ) + if ( coords_opengl ) { y = ll_round((F32)(y) * LLUI::getScaleFactor().mV[VY]); } -- cgit v1.2.3 From bd09297b8ec465a52f294092998812745ec6c566 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 3 Jun 2016 08:08:41 -0400 Subject: SL-220 - handle case that a weighted vertex includes no skin weights --- indra/llmath/llvolume.cpp | 6 ++++-- indra/newview/llskinningutil.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2918e2e272..ac6f77b5ab 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2563,11 +2563,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { wght = LLVector4(0.999f,0.f,0.f,0.f); } - for (U32 k=0; k0); // If this fails, we have a floating point precision error. joints_with_weights[k] = f_combined; + // Any weights we added above should wind up non-zero and applied to a specific bone. + // A failure here would indicate a floating point precision error in the math. + llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); } face.mWeights[cur_vertex].loadua(joints_with_weights.mV); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 732afdfa9a..b36bfc870f 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -262,6 +262,7 @@ void LLSkinningUtil::initSkinningMatrixPalette( // static void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) { + checkSkinWeights(weights, num_vertices, skin); llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for. const U32* remap = &skin->mJointRemap[0]; const S32 max_joints = skin->mJointRemap.size(); @@ -277,6 +278,7 @@ void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, con w[k] = remap[i] + f; } } + checkSkinWeights(weights, num_vertices, skin); } // static -- cgit v1.2.3 From 325c4567a6f102533c444356d752df4a9bef99a2 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 6 Jun 2016 11:11:38 +0300 Subject: MAINT-6456 Remove outdated notification (no longer used since CEF) --- indra/newview/skins/default/xui/en/notifications.xml | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 0e9dcae0ba..9e11a530f7 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8803,23 +8803,6 @@ Click and drag anywhere on the world to rotate your view SL will quit in 30 seconds due to out of memory. - - A pop-up was prevented from opening. -
- - + + -- cgit v1.2.3 From 5ebf9b3caeb95f6f196786c37847d409e94df415 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 29 Jun 2016 09:41:06 -0400 Subject: SL-426 - strings.xml fix for pec attachments, SL-402 - diagnostics for investigation --- indra/llappearance/llpolyskeletaldistortion.cpp | 6 +- indra/llcharacter/lljoint.cpp | 6 ++ indra/newview/llvoavatar.cpp | 88 ++++++++++++++++++++++++- indra/newview/llvoavatar.h | 1 + indra/newview/skins/default/xui/en/strings.xml | 4 +- 5 files changed, 99 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index a427f7c754..e9750ae6f5 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -211,9 +211,9 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex ) // joint->storeScaleForReset( newScale ); // BENTO for detailed stack tracing of params. - //std::stringstream ostr; - //ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; - //LLScopedContextString str(ostr.str()); + std::stringstream ostr; + ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; + LLScopedContextString str(ostr.str()); joint->setScale(newScale); } diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 6e6208a617..3c61047efc 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -402,6 +402,12 @@ void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh { return; } + // BENTO + // Not clear pelvis overrides are meaningful/useful. + //if (mName == "mPelvis") + //{ + // return; + //} if (!above_joint_pos_threshold(pos-getDefaultPosition())) { if (do_debug_joint(getName())) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 340f19c39e..734f3287b3 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3913,13 +3913,90 @@ void LLVOAvatar::updateHeadOffset() mHeadOffset = lerp(midEyePt, mHeadOffset, u); } } + +void LLVOAvatar::debugBodySize() const +{ + LLVector3 pelvis_scale = mPelvisp->getScale(); + + // some of the joints have not been cached + LLVector3 skull = mSkullp->getPosition(); + LL_DEBUGS("Avatar") << "skull pos " << skull << LL_ENDL; + //LLVector3 skull_scale = mSkullp->getScale(); + + LLVector3 neck = mNeckp->getPosition(); + LLVector3 neck_scale = mNeckp->getScale(); + LL_DEBUGS("Avatar") << "neck pos " << neck << " neck_scale " << neck_scale << LL_ENDL; + + LLVector3 chest = mChestp->getPosition(); + LLVector3 chest_scale = mChestp->getScale(); + LL_DEBUGS("Avatar") << "chest pos " << chest << " chest_scale " << chest_scale << LL_ENDL; + + // the rest of the joints have been cached + LLVector3 head = mHeadp->getPosition(); + LLVector3 head_scale = mHeadp->getScale(); + LL_DEBUGS("Avatar") << "head pos " << head << " head_scale " << head_scale << LL_ENDL; + + LLVector3 torso = mTorsop->getPosition(); + LLVector3 torso_scale = mTorsop->getScale(); + LL_DEBUGS("Avatar") << "torso pos " << torso << " torso_scale " << torso_scale << LL_ENDL; + + LLVector3 hip = mHipLeftp->getPosition(); + LLVector3 hip_scale = mHipLeftp->getScale(); + LL_DEBUGS("Avatar") << "hip pos " << hip << " hip_scale " << hip_scale << LL_ENDL; + + LLVector3 knee = mKneeLeftp->getPosition(); + LLVector3 knee_scale = mKneeLeftp->getScale(); + LL_DEBUGS("Avatar") << "knee pos " << knee << " knee_scale " << knee_scale << LL_ENDL; + + LLVector3 ankle = mAnkleLeftp->getPosition(); + LLVector3 ankle_scale = mAnkleLeftp->getScale(); + LL_DEBUGS("Avatar") << "ankle pos " << ankle << " ankle_scale " << ankle_scale << LL_ENDL; + + LLVector3 foot = mFootLeftp->getPosition(); + LL_DEBUGS("Avatar") << "foot pos " << foot << LL_ENDL; + + F32 new_offset = (const_cast(this))->getVisualParamWeight(AVATAR_HOVER); + LL_DEBUGS("Avatar") << "new_offset " << new_offset << LL_ENDL; + + F32 new_pelvis_to_foot = hip.mV[VZ] * pelvis_scale.mV[VZ] - + knee.mV[VZ] * hip_scale.mV[VZ] - + ankle.mV[VZ] * knee_scale.mV[VZ] - + foot.mV[VZ] * ankle_scale.mV[VZ]; + LL_DEBUGS("Avatar") << "new_pelvis_to_foot " << new_pelvis_to_foot << LL_ENDL; + + LLVector3 new_body_size; + new_body_size.mV[VZ] = new_pelvis_to_foot + + // the sqrt(2) correction below is an approximate + // correction to get to the top of the head + F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + + head.mV[VZ] * neck_scale.mV[VZ] + + neck.mV[VZ] * chest_scale.mV[VZ] + + chest.mV[VZ] * torso_scale.mV[VZ] + + torso.mV[VZ] * pelvis_scale.mV[VZ]; + + // TODO -- measure the real depth and width + new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; + new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + + LL_DEBUGS("Avatar") << "new_body_size " << new_body_size << LL_ENDL; +} + //------------------------------------------------------------------------ // postPelvisSetRecalc //------------------------------------------------------------------------ -void LLVOAvatar::postPelvisSetRecalc( void ) +void LLVOAvatar::postPelvisSetRecalc() { mRoot->updateWorldMatrixChildren(); + // BENTO extra tracing around computeBodySize() + LLVector3 body_size = mBodySize; + LLVector3 avatar_offset = mAvatarOffset; computeBodySize(); + if (mBodySize != body_size || mAvatarOffset != avatar_offset) + { + debugBodySize(); + LL_DEBUGS("Avatar") << avString() << "old mBodySize " << body_size << " old mAvatarOffset " << avatar_offset << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "new mBodySize " << mBodySize << " new mAvatarOffset " << mAvatarOffset << LL_ENDL; + } dirtyMesh(2); } //------------------------------------------------------------------------ @@ -5862,7 +5939,16 @@ void LLVOAvatar::updateVisualParams() if (mLastSkeletonSerialNum != mSkeletonSerialNum) { + // BENTO extra tracing around computeBodySize() + LLVector3 body_size = mBodySize; + LLVector3 avatar_offset = mAvatarOffset; computeBodySize(); + if (mBodySize != body_size || mAvatarOffset != avatar_offset) + { + debugBodySize(); + LL_DEBUGS("Avatar") << avString() << "old mBodySize " << body_size << " old mAvatarOffset " << avatar_offset << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "new mBodySize " << mBodySize << " new mAvatarOffset " << mAvatarOffset << LL_ENDL; + } mLastSkeletonSerialNum = mSkeletonSerialNum; mRoot->updateWorldMatrixChildren(); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 32a30c3aa8..b67aa62b06 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -367,6 +367,7 @@ protected: /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); + void debugBodySize() const; void postPelvisSetRecalc( void ); /*virtual*/ BOOL loadSkeletonNode(); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a4869b5503..e7d4491e0f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2669,8 +2669,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f Left Upper Leg Left Lower Leg Belly - Right Pec - Left Pec + Left Pec + Right Pec HUD Center 2 HUD Top Right HUD Top Center -- cgit v1.2.3 From c2320fa0d0c9d006098d0b3830b3f40ae560768d Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 29 Jun 2016 16:44:25 +0300 Subject: MAINT-2141 Sky Cloud Coverage reverts to 0.27 when toggling view back to region sky --- indra/newview/llwlparamset.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 066cb9a0ac..482a2a61e2 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -288,14 +288,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators - // keep cloud positions and coverage the same - /// TODO masking will do this later - F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal(); - F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal(); - F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal(); - F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal(); - F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal(); - LLSD srcVal; LLSD destVal; @@ -379,15 +371,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle); setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle); - - // now setup the sun properly - - // reset those cloud positions - mParamValues["cloud_pos_density1"][0] = cloudPos1X; - mParamValues["cloud_pos_density1"][1] = cloudPos1Y; - mParamValues["cloud_pos_density2"][0] = cloudPos2X; - mParamValues["cloud_pos_density2"][1] = cloudPos2Y; - mParamValues["cloud_shadow"][0] = cloudCover; } void LLWLParamSet::updateCloudScrolling(void) -- cgit v1.2.3 From 99250b4e0c26e20d9162ab10d999827f006da256 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 1 Jul 2016 15:12:55 -0400 Subject: SL-402 - more avatar height tracing in debug text --- indra/newview/llvoavatar.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 734f3287b3..11b6fec96e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3346,23 +3346,31 @@ void LLVOAvatar::updateDebugText() { debug_line += llformat(" - cof rcv:%d", last_received_cof_version); } - debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]); + debug_line += llformat(" bsz-z: %.3f", mBodySize[2]); + if (mAvatarOffset[2] != 0.0f) + { + debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]); + } bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled(); debug_line += hover_enabled ? " H" : " h"; const LLVector3& hover_offset = getHoverOffset(); if (hover_offset[2] != 0.0) { - debug_line += llformat(" hov_z: %f", hover_offset[2]); + debug_line += llformat(" hov_z: %.3f", hover_offset[2]); debug_line += llformat(" %s", (mIsSitting ? "S" : "T")); debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); } - F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32(); - static const char *elapsed_chars = "Xx*..."; - U32 bucket = U32(elapsed*2); - if (bucket < strlen(elapsed_chars)) - { - debug_line += llformat(" %c", elapsed_chars[bucket]); - } + LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); + LLVector3 normal; + LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; + resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); + F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); + debug_line += llformat(" relev %.3f", rightElev); + + LLVector3 root_pos = mRoot->getPosition(); + LLVector3 pelvis_pos = mPelvisp->getPosition(); + debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]); + addDebugText(debug_line); } if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) -- cgit v1.2.3 From 5f57257185f1535aae1967b2b6d8a40c154bef83 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 1 Jul 2016 14:52:51 -0700 Subject: MAINT-6481 FIX Media controls not present --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 3852d10c44..5dd866db80 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -214,7 +214,7 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; message.setValueLLSD("versions", versions); std::ostringstream s; -- cgit v1.2.3 From 60c0c0e0e4b504ae4e1a701265c1134220e7a8a1 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 4 Jul 2016 19:55:54 +0300 Subject: MAINT-6259 rigged items' LOD should be size dependent, not only avatar dependent --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 1 + indra/newview/llviewercontrol.cpp | 7 +++++++ indra/newview/llvovolume.cpp | 6 +++++- indra/newview/llvovolume.h | 1 + 5 files changed, 25 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6106dde734..ae900c3ecd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10218,6 +10218,17 @@ Value 1.0 + RenderRiggedLODFactor + + Comment + Controls level of detail of worn rigged meshes (multiplier for current screen area when calculated level of detail) + Persist + 1 + Type + F32 + Value + 2.5 + RenderWater Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index acbcb4f8b7..8406f09114 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -587,6 +587,7 @@ static void settings_to_globals() LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); + LLVOVolume::sRiggedLODFactor = gSavedSettings.getF32("RenderRiggedLODFactor"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 16f40fb747..abb92476d6 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -207,6 +207,12 @@ static bool handleVolumeLODChanged(const LLSD& newvalue) return true; } +static bool handleRiggedLODChanged(const LLSD& newvalue) +{ + LLVOVolume::sRiggedLODFactor = (F32)newvalue.asReal(); + return true; +} + static bool handleAvatarLODChanged(const LLSD& newvalue) { LLVOAvatar::sLODFactor = (F32) newvalue.asReal(); @@ -619,6 +625,7 @@ void settings_setup_listeners() gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); + gSavedSettings.getControl("RenderRiggedLODFactor")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8f0b233f01..55d65b8a09 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -86,6 +86,7 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; +F32 LLVOVolume::sRiggedLODFactor = 2.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; @@ -1252,7 +1253,10 @@ BOOL LLVOVolume::calcLOD() } distance = avatar->mDrawable->mDistanceWRTCamera; - radius = avatar->getBinRadius(); + F32 avatar_radius = avatar->getBinRadius(); + F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + radius = object_radius * LLVOVolume::sRiggedLODFactor; + radius = llmin(radius, avatar_radius); } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a331908320..b63d76d132 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -379,6 +379,7 @@ private: public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop static F32 sLODFactor; // LOD scale factor + static F32 sRiggedLODFactor; // Worn rigged LOD scale factor static F32 sDistanceFactor; // LOD distance factor static LLPointer sObjectMediaClient; -- cgit v1.2.3 From 85fd2dc8709405dda908b4b714f6461744c1ca22 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 5 Jul 2016 18:23:14 +0300 Subject: MAINT-6550 Graphic preset name including "\" causes preset to be unusable & preset cannot be deleted. --- indra/newview/llpresetsmanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index 9957039f72..836f63bffa 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -104,8 +104,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam if (found) { std::string path = gDirUtilp->add(dir, file); - std::string name = gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true); - + std::string name = LLURI::unescape(gDirUtilp->getBaseFileName(path, /*strip_exten = */ true)); LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL; if (PRESETS_DEFAULT != name) -- cgit v1.2.3 From 69de29d74e2171a032472f54581b4eceff1ad099 Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Wed, 6 Jul 2016 10:22:50 +0300 Subject: MAINT-6552 Contribution: Viewer sometimes crashes when opening oversized textures --- indra/newview/llviewertexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ed719ae418..ac997d7525 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1200,7 +1200,7 @@ void LLViewerFetchedTexture::loadFromFastCache() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); -- cgit v1.2.3 From ee40764c4595c68403daf091ccc68a831dd5164f Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Thu, 7 Jul 2016 02:30:30 +0300 Subject: MAINT-6552 One more nullcheck --- indra/newview/llviewertexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ac997d7525..178aa1e646 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1981,7 +1981,7 @@ bool LLViewerFetchedTexture::updateFetch() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); -- cgit v1.2.3 From 9b7f38f6fb1a4b19c5cc7cab2f673e2bc9f5ae93 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 6 Jul 2016 17:49:47 +0300 Subject: MAINT-4066 Missing notifications --- .../newview/skins/default/xui/en/notifications.xml | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 9e11a530f7..b0d8a3cf7e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -831,6 +831,13 @@ If you no longer wish to have these abilities granted to this role, disable them yestext="Ban"/>
+ +Some residents have not been sent an invite due to being banned from the group. + + + +Unable to add banned resident to estate manager list. + + + +You have left the group '[group_name]'. + group + + + + Unable to leave group. + group + + + There are too many prims selected. Please select [MAX_PRIM_COUNT] or fewer prims and try again + fail + + + + +Too many scripts in the objects selected. Please select fewer objects and try again fail + + Payment stopped: the price paid does not match any of the pay buttons set for this object. + fail + + + + + +Autopilot canceled + + + + fail +Copy failed because you lack access to that parcel. + + + + fail +Your attachments contain too much inventory to add more. + + + + fail +The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead. + + + + fail +Unable to make payment due to system load. + + Date: Tue, 5 Jul 2016 17:52:01 +0300 Subject: MAINT-5388 File "conversation.log" created in users' root directory on Windows --- indra/llvfs/lldir.cpp | 7 +++++++ indra/newview/llconversationlog.cpp | 7 ++++++- indra/newview/lllogchat.cpp | 5 ++++- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 5f4fb8f4a0..86a15f2ef2 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -531,6 +531,13 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd case LL_PATH_PER_ACCOUNT_CHAT_LOGS: prefix = getPerAccountChatLogsDir(); + if (prefix.empty()) + { + // potentially directory was not set yet + // intentionally return a blank string to the caller + LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; + return std::string(); + } break; case LL_PATH_LOGS: diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 05c7e6caa5..4e69896b69 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -448,7 +448,12 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s std::string LLConversationLog::getFileName() { std::string filename = "conversation"; - return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename) + ".log"; + std::string log_address = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + if (!log_address.empty()) + { + log_address += ".log"; + } + return log_address; } bool LLConversationLog::saveToFile(const std::string& filename) diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 639641d1c2..485d4677b1 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -244,7 +244,10 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename = cleanFileName(filename); filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); - filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + if (!filename.empty()) + { + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } return filename; } -- cgit v1.2.3 From 3bc8a974400bccc05d05984adb103f98c43c86ab Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 5 Jul 2016 14:42:47 -0400 Subject: SL-402 - update mBodySize more frequently to avoid inconsistent vertical positioning of avatar. --- indra/newview/llvoavatar.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 11b6fec96e..e3eff15815 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3596,6 +3596,12 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } mInAir = in_air; + // SL-402: with the ability to animate the position of joints + // that affect the body size calculation, computed body size + // can get stale much more easily. Simplest fix is to update + // it frequently. + computeBodySize(); + // correct for the fact that the pelvis is not necessarily the center // of the agent's physical representation root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; @@ -3995,16 +4001,7 @@ void LLVOAvatar::debugBodySize() const void LLVOAvatar::postPelvisSetRecalc() { mRoot->updateWorldMatrixChildren(); - // BENTO extra tracing around computeBodySize() - LLVector3 body_size = mBodySize; - LLVector3 avatar_offset = mAvatarOffset; computeBodySize(); - if (mBodySize != body_size || mAvatarOffset != avatar_offset) - { - debugBodySize(); - LL_DEBUGS("Avatar") << avString() << "old mBodySize " << body_size << " old mAvatarOffset " << avatar_offset << LL_ENDL; - LL_DEBUGS("Avatar") << avString() << "new mBodySize " << mBodySize << " new mAvatarOffset " << mAvatarOffset << LL_ENDL; - } dirtyMesh(2); } //------------------------------------------------------------------------ @@ -5947,16 +5944,7 @@ void LLVOAvatar::updateVisualParams() if (mLastSkeletonSerialNum != mSkeletonSerialNum) { - // BENTO extra tracing around computeBodySize() - LLVector3 body_size = mBodySize; - LLVector3 avatar_offset = mAvatarOffset; computeBodySize(); - if (mBodySize != body_size || mAvatarOffset != avatar_offset) - { - debugBodySize(); - LL_DEBUGS("Avatar") << avString() << "old mBodySize " << body_size << " old mAvatarOffset " << avatar_offset << LL_ENDL; - LL_DEBUGS("Avatar") << avString() << "new mBodySize " << mBodySize << " new mAvatarOffset " << mAvatarOffset << LL_ENDL; - } mLastSkeletonSerialNum = mSkeletonSerialNum; mRoot->updateWorldMatrixChildren(); } @@ -8397,6 +8385,12 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara } } + // Root joint + const LLVector3& pos = mRoot->getPosition(); + const LLVector3& scale = mRoot->getScale(); + apr_file_printf( file, "\t\t\n", + mRoot->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); + // Bones avatar_joint_list_t::iterator iter = mSkeleton.begin(); avatar_joint_list_t::iterator end = mSkeleton.end(); -- cgit v1.2.3 From cba0bb30380baef9ecb753149fcb1779c0c96a8e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 5 Jul 2016 16:18:50 -0400 Subject: SL-109 - little bit of log spam cleanup --- indra/llcommon/llcoros.cpp | 10 +++++----- indra/newview/llavatarrenderinfoaccountant.cpp | 2 +- indra/newview/lleventpoll.cpp | 6 +++--- indra/newview/llvoavatar.cpp | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index d16bf0160b..5bbce4325b 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -131,9 +131,9 @@ bool LLCoros::cleanup(const LLSD&) if ((previousCount < 5) || !(previousCount % 50)) { if (previousCount < 5) - LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL; + LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL; else - LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL; + LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL; } // The erase() call will invalidate its passed iterator value -- @@ -185,9 +185,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const if ((previousCount < 5) || !(previousCount % 50)) { if (previousCount < 5) - LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL; + LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL; else - LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL; + LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL; } @@ -223,7 +223,7 @@ std::string LLCoros::getName() const void LLCoros::setStackSize(S32 stacksize) { - LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; + LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; mStackSize = stacksize; } diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 5431daca32..7413dbed20 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -354,7 +354,7 @@ void LLAvatarRenderInfoAccountant::resetRenderInfoScanTimer() // are returned for a new LLViewerRegion, and is the earliest time to get render info void LLAvatarRenderInfoAccountant::scanNewRegion(const LLUUID& region_id) { - LL_INFOS("AvatarRenderInfo") << region_id << LL_ENDL; + LL_DEBUGS("AvatarRenderInfo") << region_id << LL_ENDL; // Reset the global timer so it will scan regions on the next call to ::idle LLAvatarRenderInfoAccountant::getInstance()->resetRenderInfoScanTimer(); diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 7178042b32..15110701e4 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -142,7 +142,7 @@ namespace Details int errorCount = 0; int counter = mCounter; // saved on the stack for logging. - LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL; + LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL; mAdapter = httpAdapter; @@ -170,7 +170,7 @@ namespace Details { if (status == LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT)) { // A standard timeout response we get this when there are no events. - LL_INFOS("LLEventPollImpl") << "All is very quiet on target server. It may have gone idle?" << LL_ENDL; + LL_DEBUGS("LLEventPollImpl") << "All is very quiet on target server. It may have gone idle?" << LL_ENDL; errorCount = 0; continue; } @@ -264,7 +264,7 @@ namespace Details } } } - LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL; + LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL; } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e3eff15815..d3cd85e9f4 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8974,7 +8974,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() && (all_textures.find(image_id) == all_textures.end())) { // attachment texture not previously seen. - LL_INFOS() << "attachment_texture: " << image_id.asString() << LL_ENDL; + LL_DEBUGS("ARCdetail") << "attachment_texture: " << image_id.asString() << LL_ENDL; all_textures.insert(image_id); } } @@ -8994,7 +8994,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() continue; if (all_textures.find(image_id) == all_textures.end()) { - LL_INFOS() << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL; + LL_DEBUGS("ARCdetail") << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL; all_textures.insert(image_id); } } -- cgit v1.2.3 From 880fd82d0be58aa4cc5ea16518d15fed3178aa29 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 6 Jul 2016 20:06:50 -0400 Subject: SL-424 - more proposed skeleton/slider fixes --- indra/newview/character/avatar_lad.xml | 976 ++++++++++++---------------- indra/newview/character/avatar_skeleton.xml | 81 +-- 2 files changed, 455 insertions(+), 602 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index c6294f582f..ddf497f05b 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -1421,6 +1421,11 @@ value_min="-1" value_max="1"> + + - - + offset="0.005 0 0" /> + offset="0.005 0 0" /> + offset="0.005 0 0" /> + offset="0.005 0 0" /> + offset="0.005 0 0" /> - + offset="0.01 0 0" /> + + offset="0.01 0 0" /> + offset="0.01 0 0" /> + - - - - + offset="0.007 0 0" /> + + + + scale="0.3 0 0" + offset="0 0 0" /> + offset="0.004 0 0" /> - + + + + offset = "0.0 0.0 0.0" + scale = "0.50 0.3 0.1" /> + offset = "0 0 0" + scale = "0.0 0.3 0.0" /> + offset = "0 0 0" + scale = "0.0 0.3 0.0" /> + offset = "0.001 0.013 0"/> + offset = "-0.001 -0.013 0" /> @@ -2450,42 +2455,42 @@ + offset = "-0.008 0.00 0.0" /> + offset = "-0.009 0.00 0.0025" /> + offset = "-0.009 0.00 0.0025" /> + offset = "-0.009 0.00 0.0025" /> + offset = "-0.008 0.00 0.0" /> + offset = "-0.008 0.00 -0.0015" /> + offset = "-0.008 0.00 -0.0025" /> + offset = "-0.008 0.00 -0.0015" /> @@ -2510,17 +2515,17 @@ + scale = "0.2 0.00 0.4" + offset = "0.004 0.00 0.004" /> + scale = "0.2 0.00 0.4" + offset = "0.004 0.00 0.004" /> + scale = "0.2 0.00 0.4" + offset = "0.004 0.00 0.004" /> + offset = "-0.004 0.00 0.006" /> + offset = "-0.004 0.00 0.003" /> + offset = "-0.004 0.00 0.006" /> - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + - - - - - - - - + name = "mFaceLipCornerRight" + scale = "0.0 0 0" + offset = "0 0.001 0" /> + + - + - - - - - - - - - - - - - - - - + offset = "0.0 -0.006 0.0" /> + offset = "0.0 -0.006 0.0" /> @@ -3021,55 +2951,15 @@ scale = "0.0 0.00 0.0" offset = "0.0 0.003 0.0" /> - - - - - - - - - - - - - - - - + offset = "0.0 0.006 0.0" /> + offset = "0.0 0.006 0.0" /> @@ -3140,7 +3030,7 @@ @@ -3163,46 +3053,14 @@ id="30760" group="1" name="Jaw_Angle" - value_min="-2" + value_min="-1.2" value_max="2" - value_default="0"> + value_default="0"> - - - - - - - - - - - - - - @@ -3214,42 +3072,17 @@ value_min="-2" value_max="2"> - - - - - - - - - - @@ -3305,11 +3138,10 @@ value_min="-.5" value_max="1.5"> - - + @@ -3551,209 +3383,53 @@ offset="0 0.00225 -0.0032" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + name="mFaceNoseBridge" + scale="0 0 0" + offset="0 0 -0.002" /> + - + name="mFaceNoseRight" + scale="0 0 0" + offset="0 -0.002 0" /> + + name="mFaceNoseLeft" + scale="0 0 0" + offset="0 0.002 0" /> + - + name="mFaceNoseBase" + scale="0 0 0" + offset="0 0 0.002" /> + + name="mFaceCheekUpperRight" + scale="0 0 0" + offset="0 -0.003 0" /> + - + name="mFaceCheekUpperLeft" + scale="0 0 0" + offset="0 0.003 0" /> + - + name="mFaceCheekLowerRight" + scale="0 0 0" + offset="0 -0.003 0.0032" /> + + name="mFaceCheekLowerLeft" + scale="0 0 0" + offset="0 0.003 0.0032" /> - - - + + offset="0 0 0.0016" /> @@ -3981,15 +3657,14 @@ value_max="3"> - - - + + @@ -4021,6 +3696,11 @@ + + + + + scale="0.0 -0.2 0.0" + offset="0.0 0 0.0" /> + scale="0.0 -0.2 0.0" + offset="0.0 0 0.0" /> + scale="0.0 -1.0 0.0" + offset="0.0 0.01 -0.01" /> + scale="0.0 -0.8 0.0" + offset="0.0 -0.01 -0.01" /> + + @@ -4236,28 +3926,18 @@ + offset="0 -0.0033 0.0025" /> - - - - + offset="0 -0.0033 0.002" /> - - - - + offset="0 0.0033 0.0025" /> + offset="0 0.0033 0.002" /> - + offset="0 0.00225 0.008" /> + - + offset="0 0 0" /> - + offset="0 0 0" /> + offset="0 0 0" /> - + offset="0 0 0.0075" /> + + offset="0 0 0.0061" /> + offset="0 0 -0.00" /> + offset="0 0 0.0085" /> + offset="0 0 0.0085" /> - + + @@ -4436,6 +4102,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -15254,6 +15094,10 @@ render_pass="bump"> + + + @@ -15718,6 +15562,8 @@ render_pass="bump"> + @@ -15741,6 +15587,8 @@ render_pass="bump"> + @@ -15763,6 +15611,8 @@ render_pass="bump"> + diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 025d12dd2e..2c63b8092d 100644 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -1,4 +1,4 @@ - + @@ -20,9 +20,9 @@ - - - + + + @@ -48,27 +48,30 @@ - + - - - - - - - - + + + + + + + + + + - - - - - + - - + + + + + + + @@ -103,9 +106,9 @@ - - - + + + @@ -140,9 +143,9 @@ - - - + + + @@ -210,20 +213,20 @@ - - - - + + + + + - - - - - - + + + + + + - - + - + -- cgit v1.2.3 From d59ce04495be43ab1dc68c1a78b3ca6eb2e7b01e Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 7 Jul 2016 09:10:39 -0700 Subject: MAINT-6527 FIX -volume plays at full amount +50m away - volume was not set for media outside attenuation zone so played at random value --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 5dd866db80..fdad990b7c 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -189,6 +189,7 @@ void MediaPluginLibVLC::playMedia() gVLCCallbackContext.texture_pixels = mPixels; gVLCCallbackContext.mp = gLibVLCMediaPlayer; + libvlc_audio_set_volume(gLibVLCMediaPlayer, 0); libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); libvlc_media_player_play(gLibVLCMediaPlayer); -- cgit v1.2.3 From 888ed6d620619d3ce6dddcc8e453c3f1e6713e99 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 8 Jul 2016 14:51:30 -0400 Subject: SL-242 - additional fixes for egghead slider --- indra/newview/character/avatar_lad.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ddf497f05b..6aef67f1b7 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -3926,7 +3926,7 @@ + offset="0 0.00225 0.001" /> id="186" /> -- cgit v1.2.3 From 9d8986337aca6c7909a4c5ad836874d78b4625e5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 8 Jul 2016 15:36:50 -0400 Subject: SL-242 - fix for slider param groups, added default args for skel_tool.py --- indra/newview/character/avatar_lad.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 6aef67f1b7..76a603db06 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -3897,7 +3897,7 @@ -- cgit v1.2.3 From 2929922ef2094dc0f2c2659de1d459b50aafe866 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 11 Jul 2016 18:00:59 -0400 Subject: SL-242 - more tweaks around alt eyes and wings. Alt eyes are now parented to face root, and alt eyes animate along with the original eyes inside the LLHeadRotMotion code. --- indra/llcharacter/llheadrotmotion.cpp | 201 ++++++++----- indra/llcharacter/llheadrotmotion.h | 4 + indra/newview/character/avatar_lad.xml | 450 ++++++++++++++++++---------- indra/newview/character/avatar_skeleton.xml | 10 +- 4 files changed, 429 insertions(+), 236 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index 812c4201af..e91de7a11d 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -285,7 +285,10 @@ LLEyeMotion::LLEyeMotion(const LLUUID &id) : LLMotion(id) mName = "eye_rot"; mLeftEyeState = new LLJointState; + mAltLeftEyeState = new LLJointState; + mRightEyeState = new LLJointState; + mAltRightEyeState = new LLJointState; } @@ -318,18 +321,38 @@ LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character) return STATUS_FAILURE; } + mAltLeftEyeState->setJoint( character->getJoint("mFaceEyeAltLeft") ); + if ( ! mAltLeftEyeState->getJoint() ) + { + LL_INFOS() << getName() << ": Can't get alt left eyeball joint." << LL_ENDL; + return STATUS_FAILURE; + } + mRightEyeState->setJoint( character->getJoint("mEyeRight") ); if ( ! mRightEyeState->getJoint() ) { - LL_INFOS() << getName() << ": Can't get Right eyeball joint." << LL_ENDL; + LL_INFOS() << getName() << ": Can't get right eyeball joint." << LL_ENDL; + return STATUS_FAILURE; + } + + mAltRightEyeState->setJoint( character->getJoint("mFaceEyeAltRight") ); + if ( ! mAltRightEyeState->getJoint() ) + { + LL_INFOS() << getName() << ": Can't get alt right eyeball joint." << LL_ENDL; return STATUS_FAILURE; } mLeftEyeState->setUsage(LLJointState::ROT); + mAltLeftEyeState->setUsage(LLJointState::ROT); + mRightEyeState->setUsage(LLJointState::ROT); + mAltRightEyeState->setUsage(LLJointState::ROT); addJointState( mLeftEyeState ); + addJointState( mAltLeftEyeState ); + addJointState( mRightEyeState ); + addJointState( mAltRightEyeState ); return STATUS_SUCCESS; } @@ -343,17 +366,98 @@ BOOL LLEyeMotion::onActivate() return TRUE; } - //----------------------------------------------------------------------------- -// LLEyeMotion::onUpdate() +// LLEyeMotion::adjustEyeTarget() //----------------------------------------------------------------------------- -BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) +void LLEyeMotion::adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state) { // Compute eye rotation. + BOOL has_eye_target = FALSE; LLQuaternion target_eye_rot; LLVector3 eye_look_at; F32 vergence; + if (targetPos) + { + LLVector3 skyward(0.f, 0.f, 1.f); + LLVector3 left; + LLVector3 up; + + eye_look_at = *targetPos; + has_eye_target = TRUE; + F32 lookAtDistance = eye_look_at.normVec(); + + left.setVec(skyward % eye_look_at); + up.setVec(eye_look_at % left); + + target_eye_rot = LLQuaternion(eye_look_at, left, up); + // convert target rotation to head-local coordinates + target_eye_rot *= ~mHeadJoint->getWorldRotation(); + // eliminate any Euler roll - we're lucky that roll is applied last. + F32 roll, pitch, yaw; + target_eye_rot.getEulerAngles(&roll, &pitch, &yaw); + target_eye_rot.setQuat(0.0f, pitch, yaw); + // constrain target orientation to be in front of avatar's face + target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE); + + // calculate vergence + F32 interocular_dist = (left_eye_state.getJoint()->getWorldPosition() - right_eye_state.getJoint()->getWorldPosition()).magVec(); + vergence = -atan2((interocular_dist / 2.f), lookAtDistance); + llclamp(vergence, -F_PI_BY_TWO, 0.f); + } + else + { + target_eye_rot = LLQuaternion::DEFAULT; + vergence = 0.f; + } + + //RN: subtract 4 degrees to account for foveal angular offset relative to pupil + vergence += 4.f * DEG_TO_RAD; + + // calculate eye jitter + LLQuaternion eye_jitter_rot; + + // vergence not too high... + if (vergence > -0.05f) + { + //...go ahead and jitter + eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw); + } + else + { + //...or don't + eye_jitter_rot.loadIdentity(); + } + + // calculate vergence of eyes as an object gets closer to the avatar's head + LLQuaternion vergence_quat; + + if (has_eye_target) + { + vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f)); + } + else + { + vergence_quat.loadIdentity(); + } + + // calculate eye rotations + LLQuaternion left_eye_rot = target_eye_rot; + left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot; + + LLQuaternion right_eye_rot = target_eye_rot; + vergence_quat.transQuat(); + right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot; + + left_eye_state.setRotation( left_eye_rot ); + right_eye_state.setRotation( right_eye_rot ); +} + +//----------------------------------------------------------------------------- +// LLEyeMotion::onUpdate() +//----------------------------------------------------------------------------- +BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) +{ //calculate jitter if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime) { @@ -426,83 +530,10 @@ BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) } } - BOOL has_eye_target = FALSE; LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); - if (targetPos) - { - LLVector3 skyward(0.f, 0.f, 1.f); - LLVector3 left; - LLVector3 up; - - eye_look_at = *targetPos; - has_eye_target = TRUE; - F32 lookAtDistance = eye_look_at.normVec(); - - left.setVec(skyward % eye_look_at); - up.setVec(eye_look_at % left); - - target_eye_rot = LLQuaternion(eye_look_at, left, up); - // convert target rotation to head-local coordinates - target_eye_rot *= ~mHeadJoint->getWorldRotation(); - // eliminate any Euler roll - we're lucky that roll is applied last. - F32 roll, pitch, yaw; - target_eye_rot.getEulerAngles(&roll, &pitch, &yaw); - target_eye_rot.setQuat(0.0f, pitch, yaw); - // constrain target orientation to be in front of avatar's face - target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE); - - // calculate vergence - F32 interocular_dist = (mLeftEyeState->getJoint()->getWorldPosition() - mRightEyeState->getJoint()->getWorldPosition()).magVec(); - vergence = -atan2((interocular_dist / 2.f), lookAtDistance); - llclamp(vergence, -F_PI_BY_TWO, 0.f); - } - else - { - target_eye_rot = LLQuaternion::DEFAULT; - vergence = 0.f; - } - - //RN: subtract 4 degrees to account for foveal angular offset relative to pupil - vergence += 4.f * DEG_TO_RAD; - - // calculate eye jitter - LLQuaternion eye_jitter_rot; - - // vergence not too high... - if (vergence > -0.05f) - { - //...go ahead and jitter - eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw); - } - else - { - //...or don't - eye_jitter_rot.loadIdentity(); - } - - // calculate vergence of eyes as an object gets closer to the avatar's head - LLQuaternion vergence_quat; - - if (has_eye_target) - { - vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f)); - } - else - { - vergence_quat.loadIdentity(); - } - - // calculate eye rotations - LLQuaternion left_eye_rot = target_eye_rot; - left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot; - - LLQuaternion right_eye_rot = target_eye_rot; - vergence_quat.transQuat(); - right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot; - - mLeftEyeState->setRotation( left_eye_rot ); - mRightEyeState->setRotation( right_eye_rot ); + adjustEyeTarget(targetPos, *mLeftEyeState, *mRightEyeState); + adjustEyeTarget(targetPos, *mAltLeftEyeState, *mAltRightEyeState); return TRUE; } @@ -519,11 +550,23 @@ void LLEyeMotion::onDeactivate() joint->setRotation(LLQuaternion::DEFAULT); } + joint = mAltLeftEyeState->getJoint(); + if (joint) + { + joint->setRotation(LLQuaternion::DEFAULT); + } + joint = mRightEyeState->getJoint(); if (joint) { joint->setRotation(LLQuaternion::DEFAULT); } + + joint = mAltRightEyeState->getJoint(); + if (joint) + { + joint->setRotation(LLQuaternion::DEFAULT); + } } // End diff --git a/indra/llcharacter/llheadrotmotion.h b/indra/llcharacter/llheadrotmotion.h index 569dbef2dd..53ae1813bc 100644 --- a/indra/llcharacter/llheadrotmotion.h +++ b/indra/llcharacter/llheadrotmotion.h @@ -176,6 +176,8 @@ public: // it will be deactivated virtual BOOL onActivate(); + void adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state); + // called per time step // must return TRUE while it is active, and // must return FALSE when the motion is completed. @@ -193,6 +195,8 @@ public: LLJoint *mHeadJoint; LLPointer mLeftEyeState; LLPointer mRightEyeState; + LLPointer mAltLeftEyeState; + LLPointer mAltRightEyeState; LLFrameTimer mEyeJitterTimer; F32 mEyeJitterTime; diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 76a603db06..e9ce4725e5 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -807,6 +807,39 @@ + + + + + + + + + + + + + @@ -1163,56 +1196,57 @@ name="mEyeRight" scale="0 0 0" offset="0 -.009 0" /> - - + offset="0 .0090 0" /> - + offset="0 -.0090 0" /> + + offset="0 .0090 0" /> + offset="0 -.0090 0" /> + + offset="0 .0090 0" /> + offset="0 -.0090 0" /> + offset="0 .0090 0" /> + offset="0 -.0090 0" /> + offset="0 .0090 0" /> + offset="0 -.0090 0" /> - - - + offset="0 0 -.004" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1584,6 +1488,7 @@ name="mEyeRight" scale="0 0 0" offset=".005 0 0" /> + - + - + + offset="0 0 -0.001" /> - + offset="0 0 -0.001" /> + + + + + @@ -3173,6 +3088,16 @@ name="mFaceEyeLidUpperLeft" scale="0 0.1 0.2" offset=" 0 0 0" /> + + + + @@ -3351,6 +3276,16 @@ name="mFaceEyebrowInnerLeft" scale="0 0 0" offset="0 0.00225 -0.0048" /> + + + + + + + + @@ -3929,6 +3874,16 @@ offset = "0.015 0.00 0.005" scale = "0.0 0.0 0.0" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -14577,6 +14706,23 @@ render_pass="bump"> + + + + + + diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 2c63b8092d..2241a12545 100644 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -21,11 +21,11 @@ - - - - - + + + + + -- cgit v1.2.3 From 75ff4382d985436197ead8b459bab80869b7f680 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 11 Jul 2016 18:19:37 -0400 Subject: SL-242 - avatar_lad.xml syntax fix, added missing scale params to some skeletal distortions. --- indra/newview/character/avatar_lad.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index e9ce4725e5..8e8cff59a5 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -810,34 +810,44 @@ -- cgit v1.2.3 From 8ae7828643fbb04a52a52abefa2133a761dd4179 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 11 Jul 2016 19:46:11 -0700 Subject: MAINT-6527 and MAINT-6528 FIX - max volume and media playing prior URLs --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index fdad990b7c..e00602bad8 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -189,10 +189,35 @@ void MediaPluginLibVLC::playMedia() gVLCCallbackContext.texture_pixels = mPixels; gVLCCallbackContext.mp = gLibVLCMediaPlayer; + // Send a "navigate begin" event. + // This is really a browser message but the QuickTime plugin did it and + // the media system relies on this message to update internal state so we must send it too + // Note: see "navigate_complete" message below too + // https://jira.secondlife.com/browse/MAINT-6528 + LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message_begin.setValue("uri", mURL); + message_begin.setValueBoolean("history_back_available", false); + message_begin.setValueBoolean("history_forward_available", false); + sendMessage(message_begin); + + // volume should be initialized - when media is in range, the distance based attenuation + // will set the correct value + // https://jira.secondlife.com/browse/MAINT-6527 libvlc_audio_set_volume(gLibVLCMediaPlayer, 0); libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); libvlc_media_player_play(gLibVLCMediaPlayer); + + // Send a "navigate complete" event. + // This is really a browser message but the QuickTime plugin did it and + // the media system relies on this message to update internal state so we must send it too + // Note: see "navigate_begin" message above too + // https://jira.secondlife.com/browse/MAINT-6528 + LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message_complete.setValue("uri", mURL); + message_complete.setValueS32("result_code", 200); + message_complete.setValue("result_string", "OK"); + sendMessage(message_complete); } //////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 6fb759b4b5bf12d78013bf7cc97ee79d728c2cd4 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 12 Jul 2016 07:56:11 -0400 Subject: update default LSL hints file to match the server version --- .../newview/app_settings/keywords_lsl_default.xml | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/keywords_lsl_default.xml b/indra/newview/app_settings/keywords_lsl_default.xml index bb23ec04dc..d641883d5a 100644 --- a/indra/newview/app_settings/keywords_lsl_default.xml +++ b/indra/newview/app_settings/keywords_lsl_default.xml @@ -1007,7 +1007,7 @@ type integer value - 0x800 + 0x800 tooltip @@ -1617,7 +1617,7 @@ type string value - 0x0A0x0A0x0A + \\n\\n\\n tooltip Indicates the last line of a notecard was read. @@ -5511,7 +5511,7 @@ type integer value - 0x40 + 0x40 tooltip Controls whether the object can be grabbed.\nA grab is the default action when in third person, and is available as the hand tool in build mode. This is useful for physical objects that you don't want other people to be able to trivially disturb. The default is FALSE @@ -5520,7 +5520,7 @@ type integer value - 0x400 + 0x400 tooltip Prevent click-and-drag movement on all prims in the object. @@ -9802,15 +9802,17 @@ return string arguments - - Error - + + + Error + type integer tooltip An Experience error code to translate. - - + + + tooltip Returns a string describing the error code passed or the string corresponding with XP_ERROR_UNKNOWN_ERROR if the value is not a valid Experience error code. @@ -10160,7 +10162,7 @@ Parameters type - integer + list tooltip A list of PRIM_* property constants to return values of. @@ -10251,7 +10253,7 @@ Parameters type - integer + list tooltip PRIM_* flags. @@ -12172,7 +12174,7 @@ First type - string + integer tooltip Index of the first key to return. @@ -12181,7 +12183,7 @@ Count type - string + integer tooltip The number of keys to return. @@ -14797,7 +14799,7 @@ arguments - AvatarID + AgentID type key -- cgit v1.2.3 From b73137ca17f4ecf58ac6c695da5733fcb6b9edf2 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 12 Jul 2016 08:42:10 -0400 Subject: SL-242 - eyelid slider fix --- indra/newview/character/avatar_lad.xml | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 8e8cff59a5..5ce08fc732 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -3699,16 +3699,6 @@ - - - - -- cgit v1.2.3 From 3e60211e47a0b42e43b2d715e03446f80e1681cd Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 12 Jul 2016 17:33:07 +0300 Subject: line endings fix --- indra/newview/llfloaterimnearbychat.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 08db68d44d..257b39a7dd 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -855,14 +855,14 @@ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 else { // Hack: ChatFromViewer doesn't allow negative channels - msg->newMessage("ScriptDialogReply"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgentID); - msg->addUUID("SessionID", gAgentSessionID); - msg->nextBlock("Data"); - msg->addUUID("ObjectID", gAgentID); - msg->addS32("ChatChannel", channel); - msg->addS32("ButtonIndex", 0); + msg->newMessage("ScriptDialogReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + msg->nextBlock("Data"); + msg->addUUID("ObjectID", gAgentID); + msg->addS32("ChatChannel", channel); + msg->addS32("ButtonIndex", 0); msg->addString("ButtonLabel", utf8_out_text); } -- cgit v1.2.3 From a1655f032dc68b246ac7e847e408c15a29df7ece Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 12 Jul 2016 15:06:48 -0400 Subject: SL-424 - slider eye fixes, tail scaling with height --- indra/newview/character/avatar_lad.xml | 66 +++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 5ce08fc732..9c7e50e8bb 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -850,6 +850,37 @@ scale="0 0 0" offset="-0.03 -0.03 0" /> + + + + + + + + + + + + + @@ -1992,23 +2023,34 @@ + name="mEyeLeft" + scale="0 0 0" + offset="-.005 0 0" /> + name="mEyeRight" + scale="0 0 0" + offset="-.005 0 0" /> - + offset="-.005 0 0" /> + + + + + offset="0 0 0" /> + offset="0 0 0" /> + offset="0 0 0" /> + offset="0 0 0" /> -- cgit v1.2.3 From 32e8646e7ad79e127cc1f2faa675da6bdcfbef0f Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Thu, 14 Jul 2016 18:51:00 +0300 Subject: MAINT-6559 Fixed a constant in Mesh Streaming calculation --- indra/newview/llmeshrepository.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 39ebf9f95b..c3d41c65a6 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4098,7 +4098,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32 } } - F32 max_area = 102932.f; //area of circle that encompasses region + F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559) F32 min_area = 1.f; F32 high_area = llmin(F_PI*dmid*dmid, max_area); -- cgit v1.2.3 From 799f21616ca80962bd26a889814b2a5cfa882c46 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 18 Jul 2016 11:26:39 +0300 Subject: MAINT-6520 Add a way to see worn temp attachments. --- indra/newview/llagentwearables.cpp | 24 ++ indra/newview/llagentwearables.h | 2 + indra/newview/llappearancemgr.cpp | 8 + indra/newview/llappearancemgr.h | 6 + indra/newview/llpanelwearing.cpp | 251 +++++++++++++++++++++ indra/newview/llpanelwearing.h | 33 +++ indra/newview/llviewermenu.h | 1 + .../skins/default/xui/en/menu_wearing_tab.xml | 7 + .../skins/default/xui/en/panel_outfits_wearing.xml | 41 ++++ 9 files changed, 373 insertions(+) (limited to 'indra') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 8a65aa6a89..718c1c2251 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1373,6 +1373,30 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array // LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL; } +std::vector LLAgentWearables::getTempAttachments() +{ + llvo_vec_t temp_attachs; + if (isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *objectp = (*attachment_iter); + if (objectp && objectp->isTempAttachment()) + { + temp_attachs.push_back(objectp); + } + } + } + } + return temp_attachs; +} + void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove) { if (!isAgentAvatarValid()) return; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 1004482020..b27698fd8f 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -185,6 +185,8 @@ public: static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); + static llvo_vec_t getTempAttachments(); + //-------------------------------------------------------------------- // Signals //-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a1d9786321..4a4361e94b 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3916,6 +3916,10 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << LL_ENDL; mAttachmentInvLinkEnabled = val; } +boost::signals2::connection LLAppearanceMgr::setAttachmentsChangedCallback(attachments_changed_callback_t cb) +{ + return mAttachmentsChangeSignal.connect(cb); +} void dumpAttachmentSet(const std::set& atts, const std::string& msg) { @@ -3942,6 +3946,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); LLAttachmentsMgr::instance().onAttachmentArrived(item_id); + + mAttachmentsChangeSignal(); } void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) @@ -3962,6 +3968,8 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; } + + mAttachmentsChangeSignal(); } BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 7069da7352..07ae5fba86 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -225,6 +225,10 @@ public: void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } std::string getAppearanceServiceURL() const; + typedef boost::function attachments_changed_callback_t; + typedef boost::signals2::signal attachments_changed_signal_t; + boost::signals2::connection setAttachmentsChangedCallback(attachments_changed_callback_t cb); + private: @@ -268,6 +272,8 @@ private: LLTimer mInFlightTimer; static bool mActive; + attachments_changed_signal_t mAttachmentsChangeSignal; + std::auto_ptr mUnlockOutfitTimer; // Set of temp attachment UUIDs that should be removed diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index d0353259a5..796372ba04 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -30,13 +30,19 @@ #include "lltoggleablemenu.h" +#include "llagent.h" +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" #include "llappearancemgr.h" #include "llfloatersidepanelcontainer.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llmenubutton.h" +#include "llscrolllistctrl.h" #include "llviewermenu.h" +#include "llviewerregion.h" #include "llwearableitemslist.h" #include "llsdserialize.h" #include "llclipboard.h" @@ -146,11 +152,47 @@ protected: menu->setItemVisible("detach", allow_detach); menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach); menu->setItemVisible("show_original", mUUIDs.size() == 1); + menu->setItemVisible("edit_item", FALSE); } }; ////////////////////////////////////////////////////////////////////////// +class LLTempAttachmentsContextMenu : public LLListContextMenu +{ +public: + LLTempAttachmentsContextMenu(LLPanelWearing* panel_wearing) + : mPanelWearing(panel_wearing) + {} +protected: + /* virtual */ LLContextMenu* createMenu() + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + + registrar.add("Wearing.EditItem", boost::bind(&LLPanelWearing::onEditAttachment, mPanelWearing)); + registrar.add("Wearing.Detach", boost::bind(&LLPanelWearing::onRemoveAttachment, mPanelWearing)); + LLContextMenu* menu = createFromFile("menu_wearing_tab.xml"); + + updateMenuItemsVisibility(menu); + + return menu; + } + + void updateMenuItemsVisibility(LLContextMenu* menu) + { + menu->setItemVisible("take_off", FALSE); + menu->setItemVisible("detach", TRUE); + menu->setItemVisible("edit_outfit_separator", TRUE); + menu->setItemVisible("show_original", FALSE); + menu->setItemVisible("edit_item", TRUE); + menu->setItemVisible("edit", FALSE); + } + + LLPanelWearing* mPanelWearing; +}; + +////////////////////////////////////////////////////////////////////////// + std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null; static LLPanelInjector t_panel_wearing("panel_wearing"); @@ -159,30 +201,47 @@ LLPanelWearing::LLPanelWearing() : LLPanelAppearanceTab() , mCOFItemsList(NULL) , mIsInitialized(false) + , mAttachmentsChangedConnection() { mCategoriesObserver = new LLInventoryCategoriesObserver(); mGearMenu = new LLWearingGearMenu(this); mContextMenu = new LLWearingContextMenu(); + mAttachmentsMenu = new LLTempAttachmentsContextMenu(this); } LLPanelWearing::~LLPanelWearing() { delete mGearMenu; delete mContextMenu; + delete mAttachmentsMenu; if (gInventory.containsObserver(mCategoriesObserver)) { gInventory.removeObserver(mCategoriesObserver); } delete mCategoriesObserver; + + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } } BOOL LLPanelWearing::postBuild() { + mAccordionCtrl = getChild("wearables_accordion"); + mWearablesTab = getChild("tab_wearables"); + mAttachmentsTab = getChild("tab_temp_attachments"); + mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLPanelWearing::onAccordionTabStateChanged, this)); + mCOFItemsList = getChild("cof_items_list"); mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3)); + mTempItemsList = getChild("temp_attachments_list"); + mTempItemsList->setFgUnselectedColor(LLColor4::white); + mTempItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onTempAttachmentsListRightClick, this, _1, _2, _3)); + LLMenuButton* menu_gear_btn = getChild("options_gear_btn"); menu_gear_btn->setMenu(mGearMenu->getMenu()); @@ -223,6 +282,44 @@ void LLPanelWearing::onOpen(const LLSD& /*info*/) } } +void LLPanelWearing::draw() +{ + if (mUpdateTimer.getStarted() && (mUpdateTimer.getElapsedTimeF32() > 0.1)) + { + mUpdateTimer.stop(); + updateAttachmentsList(); + } + LLPanel::draw(); +} + +void LLPanelWearing::onAccordionTabStateChanged() +{ + if(mAttachmentsTab->isExpanded()) + { + startUpdateTimer(); + mAttachmentsChangedConnection = LLAppearanceMgr::instance().setAttachmentsChangedCallback(boost::bind(&LLPanelWearing::startUpdateTimer, this)); + } + else + { + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } + } +} + +void LLPanelWearing::startUpdateTimer() +{ + if (!mUpdateTimer.getStarted()) + { + mUpdateTimer.start(); + } + else + { + mUpdateTimer.reset(); + } +} + // virtual void LLPanelWearing::setFilterSubString(const std::string& string) { @@ -251,6 +348,124 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata) return false; } +void LLPanelWearing::updateAttachmentsList() +{ + std::vector attachs = LLAgentWearables::getTempAttachments(); + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + if(!attachs.empty()) + { + if(!populateAttachmentsList()) + { + requestAttachmentDetails(); + } + } + else + { + std::string no_attachments = getString("no_attachments"); + LLSD row; + row["columns"][0]["column"] = "text"; + row["columns"][0]["value"] = no_attachments; + row["columns"][0]["font"] = "SansSerifBold"; + mTempItemsList->addElement(row); + } +} + +bool LLPanelWearing::populateAttachmentsList(bool update) +{ + bool populated = true; + if(mTempItemsList) + { + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + std::vector attachs = LLAgentWearables::getTempAttachments(); + + std::string icon_name = LLInventoryIcon::getIconName(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT); + for (std::vector::iterator iter = attachs.begin(); + iter != attachs.end(); ++iter) + { + LLViewerObject *attachment = *iter; + LLSD row; + row["id"] = attachment->getID(); + row["columns"][0]["column"] = "icon"; + row["columns"][0]["type"] = "icon"; + row["columns"][0]["value"] = icon_name; + row["columns"][1]["column"] = "text"; + if(mObjectNames.count(attachment->getID()) && !mObjectNames[attachment->getID()].empty()) + { + row["columns"][1]["value"] = mObjectNames[attachment->getID()]; + } + else if(update) + { + row["columns"][1]["value"] = attachment->getID(); + populated = false; + } + else + { + row["columns"][1]["value"] = "Loading..."; + populated = false; + } + mTempItemsList->addElement(row); + mAttachmentsMap[attachment->getID()] = attachment; + } + } + return populated; +} + +void LLPanelWearing::requestAttachmentDetails() +{ + LLSD body; + std::string url = gAgent.getRegion()->getCapability("AttachmentResources"); + if (!url.empty()) + { + LLCoros::instance().launch("LLPanelWearing::getAttachmentLimitsCoro", + boost::bind(&LLPanelWearing::getAttachmentLimitsCoro, this, url)); + } +} + +void LLPanelWearing::getAttachmentLimitsCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL; + return; + } + + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + setAttachmentDetails(result); +} + + +void LLPanelWearing::setAttachmentDetails(LLSD content) +{ + mObjectNames.clear(); + S32 number_attachments = content["attachments"].size(); + for(int i = 0; i < number_attachments; i++) + { + S32 number_objects = content["attachments"][i]["objects"].size(); + for(int j = 0; j < number_objects; j++) + { + LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID(); + std::string name = content["attachments"][i]["objects"][j]["name"].asString(); + mObjectNames[task_id] = name; + } + } + if(!mObjectNames.empty()) + { + populateAttachmentsList(true); + } +} + boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb) { if (!mCOFItemsList) return boost::signals2::connection(); @@ -270,6 +485,20 @@ void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) mContextMenu->show(ctrl, selected_uuids, x, y); } +void LLPanelWearing::onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) +{ + LLScrollListCtrl* list = dynamic_cast(ctrl); + if (!list) return; + list->selectItemAt(x, y, MASK_NONE); + uuid_vec_t selected_uuids; + + if(list->getCurrentID().notNull()) + { + selected_uuids.push_back(list->getCurrentID()); + mAttachmentsMenu->show(ctrl, selected_uuids, x, y); + } +} + bool LLPanelWearing::hasItemSelected() { return mCOFItemsList->getSelectedItem() != NULL; @@ -280,6 +509,28 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const mCOFItemsList->getSelectedUUIDs(selected_uuids); } +void LLPanelWearing::onEditAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + handle_object_edit(); + } +} + +void LLPanelWearing::onRemoveAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + LLSelectMgr::getInstance()->sendDropAttachment(); + } +} + void LLPanelWearing::copyToClipboard() { std::string text; diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index 9a212b3cca..c5cb79092a 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -31,9 +31,14 @@ // newview #include "llpanelappearancetab.h" +#include "llselectmgr.h" +#include "lltimer.h" +class LLAccordionCtrl; +class LLAccordionCtrlTab; class LLInventoryCategoriesObserver; class LLListContextMenu; +class LLScrollListCtrl; class LLWearableItemsList; class LLWearingGearMenu; @@ -52,6 +57,8 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(const LLSD& info); /*virtual*/ void setFilterSubString(const std::string& string); @@ -62,17 +69,43 @@ public: /*virtual*/ void copyToClipboard(); + void startUpdateTimer(); + void updateAttachmentsList(); + boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb); bool hasItemSelected(); + bool populateAttachmentsList(bool update = false); + void onAccordionTabStateChanged(); + void setAttachmentDetails(LLSD content); + void requestAttachmentDetails(); + void onEditAttachment(); + void onRemoveAttachment(); + private: void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + void onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + + void getAttachmentLimitsCoro(std::string url); LLInventoryCategoriesObserver* mCategoriesObserver; LLWearableItemsList* mCOFItemsList; + LLScrollListCtrl* mTempItemsList; LLWearingGearMenu* mGearMenu; LLListContextMenu* mContextMenu; + LLListContextMenu* mAttachmentsMenu; + + LLAccordionCtrlTab* mWearablesTab; + LLAccordionCtrlTab* mAttachmentsTab; + LLAccordionCtrl* mAccordionCtrl; + + std::map mAttachmentsMap; + + std::map mObjectNames; + + boost::signals2::connection mAttachmentsChangedConnection; + LLFrameTimer mUpdateTimer; bool mIsInitialized; }; diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 2f9bf7f714..a553bb79a2 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -108,6 +108,7 @@ void handle_look_at_selection(const LLSD& param); void handle_zoom_to_object(LLUUID object_id); void handle_object_return(); void handle_object_delete(); +void handle_object_edit(); void handle_buy_land(); diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml index 44b2727671..75c1de24aa 100644 --- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml +++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml @@ -27,6 +27,13 @@ + + + + + No attachments worn. + + + + + + + + + + + Date: Thu, 14 Jul 2016 19:31:35 +0300 Subject: MAINT-6572 FIXED UI freezes when clicking on a specific folder in the inventory --- indra/llui/llui.cpp | 2 +- indra/llui/llview.cpp | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index aabc7ed2e4..f790d8e005 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -522,7 +522,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path) else { std::string part(ti->begin(), ti->end()); - context = context->findChildView(part, recurse); + context = context->findChildView(LLURI::unescape(part), recurse); recurse = false; } } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 62c3f401bf..e1d9b1a487 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -391,7 +391,27 @@ static void buildPathname(std::ostream& out, const LLView* view) buildPathname(out, view->getParent()); // Build pathname into ostream on the way back from recursion. - out << '/' << view->getName(); + out << '/'; + + // substitute all '/' in name with appropriate code + std::string name = view->getName(); + std::size_t found = name.find('/'); + std::size_t start = 0; + while (found != std::string::npos) + { + std::size_t sub_len = found - start; + if (sub_len > 0) + { + out << name.substr(start, sub_len); + } + out << "%2F"; + start = found + 1; + found = name.find('/', start); + } + if (start < name.size()) + { + out << name.substr(start, name.size() - start); + } } std::string LLView::getPathname() const -- cgit v1.2.3 From b652774324e0cdf01cf7a75a45abb05391654809 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 18 Jul 2016 17:28:02 +0300 Subject: Backed out changeset: a1a0a055e892 --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/llappviewer.cpp | 1 - indra/newview/llviewercontrol.cpp | 7 ------- indra/newview/llvovolume.cpp | 6 +----- indra/newview/llvovolume.h | 1 - 5 files changed, 1 insertion(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ae900c3ecd..6106dde734 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10218,17 +10218,6 @@ Value 1.0 - RenderRiggedLODFactor - - Comment - Controls level of detail of worn rigged meshes (multiplier for current screen area when calculated level of detail) - Persist - 1 - Type - F32 - Value - 2.5 - RenderWater Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8406f09114..acbcb4f8b7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -587,7 +587,6 @@ static void settings_to_globals() LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); - LLVOVolume::sRiggedLODFactor = gSavedSettings.getF32("RenderRiggedLODFactor"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index abb92476d6..16f40fb747 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -207,12 +207,6 @@ static bool handleVolumeLODChanged(const LLSD& newvalue) return true; } -static bool handleRiggedLODChanged(const LLSD& newvalue) -{ - LLVOVolume::sRiggedLODFactor = (F32)newvalue.asReal(); - return true; -} - static bool handleAvatarLODChanged(const LLSD& newvalue) { LLVOAvatar::sLODFactor = (F32) newvalue.asReal(); @@ -625,7 +619,6 @@ void settings_setup_listeners() gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); - gSavedSettings.getControl("RenderRiggedLODFactor")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 177ad9ab3d..486f6fae61 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -86,7 +86,6 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; -F32 LLVOVolume::sRiggedLODFactor = 2.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; @@ -1253,10 +1252,7 @@ BOOL LLVOVolume::calcLOD() } distance = avatar->mDrawable->mDistanceWRTCamera; - F32 avatar_radius = avatar->getBinRadius(); - F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); - radius = object_radius * LLVOVolume::sRiggedLODFactor; - radius = llmin(radius, avatar_radius); + radius = avatar->getBinRadius(); } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index b63d76d132..a331908320 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -379,7 +379,6 @@ private: public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop static F32 sLODFactor; // LOD scale factor - static F32 sRiggedLODFactor; // Worn rigged LOD scale factor static F32 sDistanceFactor; // LOD distance factor static LLPointer sObjectMediaClient; -- cgit v1.2.3 From 070116f2120e9e3e546a09d209ee3222affc7f93 Mon Sep 17 00:00:00 2001 From: pavelkproductengine Date: Wed, 13 Jul 2016 20:28:29 +0300 Subject: MAINT-6493 SL Viewer does not respect the Windows 10 display setting size slider --- indra/llwindow/llwindow.h | 2 + indra/llwindow/llwindowwin32.cpp | 65 ++++++++++++++++++++++ indra/llwindow/llwindowwin32.h | 2 + indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llappviewer.cpp | 11 +++- indra/newview/llappviewer.h | 1 + indra/newview/llstartup.cpp | 6 +- indra/newview/llviewerwindow.cpp | 35 +++++++++++- indra/newview/llviewerwindow.h | 8 ++- .../newview/skins/default/xui/en/notifications.xml | 12 ++++ 10 files changed, 147 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0a30f4c807..a05ba8cbba 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -166,6 +166,8 @@ public: // Provide native key event data virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } + // Get system UI size based on DPI (for 96 DPI UI size should be 1.0) + virtual F32 getSystemUISize() { return 1.0; } protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 875ffe4cd4..2a39029eee 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -78,6 +78,31 @@ LPWSTR gIconResource = IDI_APPLICATION; LLW32MsgCallback gAsyncMsgCallback = NULL; +#ifndef DPI_ENUMS_DECLARED + +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#endif + +typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value); + +typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)( + _In_ HMONITOR hmonitor, + _In_ MONITOR_DPI_TYPE dpiType, + _Out_ UINT *dpiX, + _Out_ UINT *dpiY); + // // LLWindowWin32 // @@ -3878,6 +3903,46 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) return FALSE; } +F32 LLWindowWin32::getSystemUISize() +{ + float scale_value = 0; + HWND hWnd = (HWND)getPlatformWindow(); + HDC hdc = GetDC(hWnd); + HMONITOR hMonitor; + + HMODULE hShcore = LoadLibrary(L"shcore.dll"); + + if (hShcore != NULL) + { + SetProcessDpiAwarenessType pSPDA; + pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness"); + GetDpiForMonitorType pGDFM; + pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor"); + if (pSPDA != NULL && pGDFM != NULL) + { + pSPDA(PROCESS_PER_MONITOR_DPI_AWARE); + POINT pt; + UINT dpix = 0, dpiy = 0; + HRESULT hr = E_FAIL; + + // Get the DPI for the main monitor, and set the scaling factor + pt.x = 1; + pt.y = 1; + hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + scale_value = dpix / 96.0f; + } + } + else + { + LL_WARNS() << "Could not load shcore.dll library (included by from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL; + scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + } + + ReleaseDC(hWnd, hdc); + return scale_value; +} + //static std::vector LLWindowWin32::getDynamicFallbackFontList() { diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 1a775eadaf..1386321912 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -110,6 +110,8 @@ public: /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + /*virtual*/ F32 getSystemUISize(); + LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); static std::vector getDynamicFallbackFontList(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6106dde734..90ad5a605d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12792,6 +12792,17 @@ Value 1.0 + LastSystemUIScaleFactor + + Comment + Size of system UI during last run. On Windows 100% (96 DPI) system setting is 1.0 UI size + Persist + 1 + Type + F32 + Value + 1.0 + UIScrollbarSize Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index acbcb4f8b7..724eb56286 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -696,7 +696,8 @@ LLAppViewer::LLAppViewer() mPeriodicSlowFrame(LLCachedControl(gSavedSettings,"Periodic Slow Frame", FALSE)), mFastTimerLogThread(NULL), mUpdater(new LLUpdaterService()), - mSettingsLocationList(NULL) + mSettingsLocationList(NULL), + mIsFirstRun(false) { if(NULL != sInstance) { @@ -2485,7 +2486,10 @@ bool LLAppViewer::initConfiguration() if (gSavedSettings.getBOOL("FirstRunThisInstall")) { - // Note that the "FirstRunThisInstall" settings is currently unused. + // Set firstrun flag to indicate that some further init actiona should be taken + // like determining screen DPI value and so on + mIsFirstRun = true; + gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); } @@ -3142,7 +3146,8 @@ bool LLAppViewer::initWindow() .min_width(gSavedSettings.getU32("MinWindowWidth")) .min_height(gSavedSettings.getU32("MinWindowHeight")) .fullscreen(gSavedSettings.getBOOL("FullScreen")) - .ignore_pixel_depth(ignorePixelDepth); + .ignore_pixel_depth(ignorePixelDepth) + .first_run(mIsFirstRun); gViewerWindow = new LLViewerWindow(window_params); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 07bef11dbc..d4af2440be 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -318,6 +318,7 @@ private: // llcorehttp library init/shutdown helper LLAppCoreHttp mAppCoreHttp; + bool mIsFirstRun; //--------------------------------------------- //*NOTE: Mani - legacy updater stuff // Still useable? diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a2c8e7772e..4e81d78455 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -771,7 +771,11 @@ bool idle_startup() LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; } } - + display_startup(); + if (gViewerWindow->getSystemUIScaleFactorChanged()) + { + LLViewerWindow::showSystemUIScaleFactorChanged(); + } LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input } else diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c17c50fd88..f47a37fcda 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1655,7 +1655,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) mResDirty(false), mStatesDirty(false), mCurrResolutionIndex(0), - mProgressView(NULL) + mProgressView(NULL), + mSystemUIScaleFactorChanged(false) { // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to // pass its value right now. Instead, pass it a nullary function that @@ -1743,6 +1744,16 @@ LLViewerWindow::LLViewerWindow(const Params& p) gSavedSettings.setS32("FullScreenHeight",scr.mY); } + + F32 system_scale_factor = mWindow->getSystemUISize(); + if (p.first_run || gSavedSettings.getF32("LastSystemUIScaleFactor") != system_scale_factor) + { + mSystemUIScaleFactorChanged = true; + gSavedSettings.setF32("LastSystemUIScaleFactor", system_scale_factor); + gSavedSettings.setF32("UIScaleFactor", system_scale_factor); + } + + // Get the real window rect the window was created with (since there are various OS-dependent reasons why // the size of a window or fullscreen context may have been adjusted slightly...) F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); @@ -1838,6 +1849,28 @@ LLViewerWindow::LLViewerWindow(const Params& p) mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); } +//static +void LLViewerWindow::showSystemUIScaleFactorChanged() +{ + LLNotificationsUtil::add("SystemUIScaleFactorChanged", LLSD(), LLSD(), onSystemUIScaleFactorChanged); +} + +//static +bool LLViewerWindow::onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(option == 0) + { + LLFloaterReg::toggleInstanceOrBringToFront("preferences"); + LLFloater* pref_floater = LLFloaterReg::getInstance("preferences"); + LLTabContainer* tab_container = pref_floater->getChild("pref core"); + tab_container->selectTabByName("advanced1"); + + } + return false; +} + + void LLViewerWindow::initGLDefaults() { gGL.setSceneBlendType(LLRender::BT_ALPHA); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad06f00234..afe80358ca 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -155,7 +155,8 @@ public: min_width, min_height; Optional fullscreen, - ignore_pixel_depth; + ignore_pixel_depth, + first_run; Params(); }; @@ -418,6 +419,9 @@ public: void calcDisplayScale(); static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); + bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; } + static void showSystemUIScaleFactorChanged(); + private: bool shouldShowToolTipFor(LLMouseHandler *mh); @@ -431,6 +435,7 @@ private: S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter LLRect getChatConsoleRect(); // Get optimal cosole rect. + static bool onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response); private: LLWindow* mWindow; // graphical window object bool mActive; @@ -509,6 +514,7 @@ private: LLPointer mDragHoveredObject; static LLTrace::SampleStatHandle<> sMouseVelocityStat; + bool mSystemUIScaleFactorChanged; // system UI scale factor changed from last run }; // diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index b0d8a3cf7e..54e90ac496 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4071,6 +4071,18 @@ Do you want to open your Web browser to view this content? yestext="OK"/> + +System UI size factor has changed since last run. Do you want to open UI size adjustment settings page? + confirm + + + Date: Thu, 14 Jul 2016 17:10:59 +0300 Subject: MAINT-6125 Mesh avatar deforms constantly FIXED --- indra/newview/llvieweroctree.cpp | 2 +- indra/newview/llvovolume.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 023f1b92ba..86591ff4df 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -465,7 +465,7 @@ LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) { LLVector4a tmp; tmp.splat(0.f); - mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = mObjectExtents[0] = mObjectExtents[1] = tmp; mBounds[0] = node->getCenter(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8f0b233f01..fea2235175 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1753,7 +1753,10 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); compiled = TRUE; lodOrSculptChanged(drawable, compiled); - genBBoxes(FALSE); + if (!mLODChanged) + { + genBBoxes(FALSE); + } } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else -- cgit v1.2.3 From e0c2a4ac336c7ecbfe4215a02a201d685e6d14fd Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 15 Jul 2016 10:52:29 -0400 Subject: SL-126 - getting performance analysis into a non-crashing state --- indra/newview/llfasttimerview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 4a059fdc67..e9b5403dea 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -904,7 +904,8 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target base[label]["Samples"].asInteger()); } - exportCharts(baseline, target); + // BENTO - this currently crashes + // exportCharts(baseline, target); os.flush(); os.close(); -- cgit v1.2.3 From 1c4dbc64abc7ff176b5dcbbc64d0454968efad74 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Fri, 15 Jul 2016 12:18:00 -0700 Subject: MAINT-6577 FIX No sound in MOAP or browser video --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 42 +++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index e00602bad8..8ef4ee2a27 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -54,6 +54,7 @@ class MediaPluginLibVLC : void initVLC(); void playMedia(); void resetVLC(); + void setVolume(const F64 volume); static void* lock(void* data, void** p_pixels); static void unlock(void* data, void* id, void* const* raw_pixels); @@ -72,6 +73,7 @@ class MediaPluginLibVLC : struct gVLCContext gVLCCallbackContext; std::string mURL; + F64 mCurVolume; }; //////////////////////////////////////////////////////////////////////////////// @@ -90,6 +92,8 @@ MediaPluginLibVLC::MediaPluginLibVLC( LLPluginInstance::sendMessageFunction host gLibVLCMedia = 0; gLibVLCMediaPlayer = 0; + mCurVolume = 0.0; + mURL = std::string(); } @@ -200,10 +204,10 @@ void MediaPluginLibVLC::playMedia() message_begin.setValueBoolean("history_forward_available", false); sendMessage(message_begin); - // volume should be initialized - when media is in range, the distance based attenuation - // will set the correct value - // https://jira.secondlife.com/browse/MAINT-6527 - libvlc_audio_set_volume(gLibVLCMediaPlayer, 0); + // volume level gets set before VLC is initialized (thanks media system) so we have to record + // it in mCurVolume and set it again here so that volume levels are correctly initialized + setVolume(mCurVolume); + libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); libvlc_media_player_play(gLibVLCMediaPlayer); @@ -220,6 +224,28 @@ void MediaPluginLibVLC::playMedia() sendMessage(message_complete); } +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::setVolume(const F64 volume) +{ + mCurVolume = volume; + + if (gLibVLCMediaPlayer) + { + int result = libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); + if (result != 0) + { + // volume wasn't set but not much to be done here + } + } + else + { + // volume change was requested but VLC wasn't ready. + // that's okay thought because we saved the value in mCurVolume and + // the next volume change after the VLC system is initilzied will set it + } +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::receiveMessage( const char* message_string ) @@ -388,11 +414,9 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) } else if (message_name == "set_volume") { - if (gLibVLCMediaPlayer) - { - F64 volume = message_in.getValueReal("volume"); - libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); - } + // volume comes in 0 -> 1.0 + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); } } } -- cgit v1.2.3 From eebbda288d9ba4f8f3061c05ff5eb2d7b0d1cb35 Mon Sep 17 00:00:00 2001 From: ruslantproductengine Date: Mon, 18 Jul 2016 20:09:18 +0300 Subject: Backed out changeset: 5fe5ad059c05 --- indra/llrender/llglslshader.cpp | 22 ----------- indra/llrender/llglslshader.h | 1 - indra/llrender/llrender.cpp | 8 ---- indra/llrender/llrender.h | 1 - indra/llrender/llshadermgr.cpp | 1 - indra/llrender/llshadermgr.h | 3 +- .../shaders/class1/deferred/diffuseV.glsl | 11 ------ .../shaders/class1/deferred/fullbrightV.glsl | 11 ------ .../shaders/class1/objects/fullbrightV.glsl | 13 ------- .../shaders/class1/objects/simpleV.glsl | 12 +----- indra/newview/lldrawpool.cpp | 45 ---------------------- 11 files changed, 2 insertions(+), 126 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 2554ccdbe4..58c1186a3e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1274,28 +1274,6 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c } } -void LLGLSLShader::uniform1b(U32 index, GLboolean x) -{ - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map::iterator iter = mValue.find(mUniform[index]); - if (iter == mValue.end() || iter->second.mV[0] != x) - { - glUniform1iARB(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); - } - } - } -} - GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) { GLint ret = -1; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 8663a5a5ff..0746e8760a 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -125,7 +125,6 @@ public: void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v); - void uniform1b(U32 index, GLboolean b); void setMinimumAlpha(F32 minimum); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b5ed67f66a..69420dd0bb 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1466,14 +1466,6 @@ U32 LLRender::getMatrixMode() return mMatrixMode; } -void LLRender::setInverseTexCoordByY(bool v) -{ - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - if (shader) - { - shader->uniform1b(LLShaderMgr::INVERSE_TEX_Y, v); - } -} void LLRender::loadIdentity() { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 4c3547f8e4..a67fb8da52 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -355,7 +355,6 @@ public: void multMatrix(const GLfloat* m); void matrixMode(U32 mode); U32 getMatrixMode(); - void setInverseTexCoordByY(bool v); const glh::matrix4f& getModelviewMatrix(); const glh::matrix4f& getProjectionMatrix(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 7d857c6930..55f0791174 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1190,7 +1190,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("display_gamma"); - mReservedUniforms.push_back("invert_tex_y"); llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 50b7c8b9d9..394b38f832 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -215,8 +215,7 @@ public: TERRAIN_ALPHARAMP, SHINY_ORIGIN, - DISPLAY_GAMMA, - INVERSE_TEX_Y, +DISPLAY_GAMMA, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 7e83389f6e..3c026796c8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -26,13 +26,6 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; -uniform bool invert_tex_y = false; -const mat4 invTexM = mat4( - 1, 0, 0, 0, - 0,-1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 -); ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; @@ -51,10 +44,6 @@ void main() //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - if(invert_tex_y) - { - vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; - } passTextureIndex(); vary_normal = normalize(normal_matrix * normal); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 2595712882..8e899e3e0f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -26,13 +26,6 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; -uniform bool invert_tex_y = false; -const mat4 invTexM = mat4( - 1, 0, 0, 0, - 0,-1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 -); ATTRIBUTE vec3 position; @@ -69,10 +62,6 @@ void main() #endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - if(invert_tex_y) - { - vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; - } calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index a8efcd9857..fc20d3270e 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -26,14 +26,6 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; - -uniform bool invert_tex_y = false; -const mat4 invTexM = mat4( - 1, 0, 0, 0, - 0,-1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 -); ATTRIBUTE vec3 position; void passTextureIndex(); @@ -57,11 +49,6 @@ void main() vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - if(invert_tex_y) - { - vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; - } calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index c744dc1397..37a20383e2 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -27,13 +27,6 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; -uniform bool invert_tex_y = false; -const mat4 invTexM = mat4( - 1, 0, 0, 0, - 0,-1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 -); ATTRIBUTE vec3 position; void passTextureIndex(); @@ -58,10 +51,7 @@ void main() gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy; - if(invert_tex_y) - { - vary_texcoord0 = vec2(invTexM * vec4(vary_texcoord0,0,1)).xy; - } + vec3 norm = normalize(normal_matrix * normal); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index a6cf917cbd..f74164aea6 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -473,10 +473,6 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba if (params.mTextureList[i].notNull()) { gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); - if (LLViewerTexture::MEDIA_TEXTURE == params.mTextureList[i]->getType()) - { - gGL.setInverseTexCoordByY(true); - } } } } @@ -486,54 +482,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { params.mTexture->addTextureStats(params.mVSize); gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; - - if (!gPipeline.mVertexShadersEnabled) - { - if (LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType() && !params.mTextureMatrix) - { - static const float fIdntInvY[] = { - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*)fIdntInvY); - gPipeline.mTextureMatrixOps++; - - tex_setup = true; - } - } - else - { - gGL.setInverseTexCoordByY(LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType()); - } - if (params.mTextureMatrix) { tex_setup = true; gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - - if (LLViewerTexture::MEDIA_TEXTURE == params.mTexture->getType() && !gPipeline.mVertexShadersEnabled) - { - static const float fIdntInvY[] = { - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - gGL.multMatrix(fIdntInvY); - gPipeline.mMatrixOpCount++; - } - gPipeline.mTextureMatrixOps++; - - tex_setup = true; } } else -- cgit v1.2.3 From d66d8e727a377705a8be2a3de7930efe200c81c3 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 19 Jul 2016 17:21:42 +0300 Subject: MAINT-6574 object's text was not fading out over distance after lod info debugging --- indra/newview/llviewerobject.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 56dcd30a1d..72a8595845 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5022,6 +5022,12 @@ void LLViewerObject::restoreHudText() { initHudText(); } + else + { + // Restore default values + mText->setZCompare(TRUE); + mText->setDoFade(TRUE); + } mText->setColor(mHudTextColor); mText->setString(mHudText); } -- cgit v1.2.3 From 936681cb82d0ec70013430a131aa7cdbe163725b Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 25 Jul 2016 11:18:20 +0300 Subject: MAINT-6568 Detached Object Ends up in Root of Inventory --- indra/newview/llinventorymodel.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index da06cfd311..d328973bae 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -914,8 +914,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id); if( item_array ) { + LLInventoryModel::LLCategoryUpdate update(category_id, 1); + gInventory.accountForUpdate(update); + // *FIX: bit of a hack to call update server from here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -956,9 +959,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) { + LLInventoryModel::LLCategoryUpdate update(parent_id, 1); + gInventory.accountForUpdate(update); // *FIX: bit of a hack to call update server from // here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else -- cgit v1.2.3 From ee51eee6275d6238a606da028a779bb07dc3b64c Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 19 Jul 2016 19:33:50 +0300 Subject: MAINT-6259 rigged items' LOD should be size dependent, not only avatar dependent --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 1 + indra/newview/llviewercontrol.cpp | 7 +++++++ indra/newview/llvovolume.cpp | 26 +++++++++++++++++--------- indra/newview/llvovolume.h | 3 ++- 5 files changed, 38 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 90ad5a605d..c3d7d67c86 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10218,6 +10218,17 @@ Value 1.0 + RenderRiggedFactorMultiplier + + Comment + Affects level of detail for worn rigged meshes + Persist + 1 + Type + F32 + Value + 7.5 + RenderWater Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 724eb56286..950692a788 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -587,6 +587,7 @@ static void settings_to_globals() LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); + LLVOVolume::sRiggedFactorMultiplier = gSavedSettings.getF32("RenderRiggedFactorMultiplier"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 16f40fb747..5e74e9f019 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -207,6 +207,12 @@ static bool handleVolumeLODChanged(const LLSD& newvalue) return true; } +static bool handleRiggedLODChanged(const LLSD& newvalue) +{ + LLVOVolume::sRiggedFactorMultiplier = (F32)newvalue.asReal(); + return true; +} + static bool handleAvatarLODChanged(const LLSD& newvalue) { LLVOAvatar::sLODFactor = (F32) newvalue.asReal(); @@ -619,6 +625,7 @@ void settings_setup_listeners() gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); + gSavedSettings.getControl("RenderRiggedFactorMultiplier")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index fde997d54e..5fc571bf1d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -86,6 +86,7 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; +F32 LLVOVolume::sRiggedFactorMultiplier = 6.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; @@ -1213,18 +1214,18 @@ void LLVOVolume::sculpt() } } -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) { S32 cur_detail; if (LLPipeline::sDynamicLOD) { // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; + F32 tan_angle = (lod_factor*radius) / distance; cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); } else { - cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3); + cur_detail = llclamp((S32)(sqrtf(radius)*lod_factor*4.f), 0, 3); } return cur_detail; } @@ -1240,6 +1241,7 @@ BOOL LLVOVolume::calcLOD() F32 radius; F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; if (mDrawable->isState(LLDrawable::RIGGED)) { @@ -1251,22 +1253,27 @@ BOOL LLVOVolume::calcLOD() return FALSE; } + // Note: when changing, take note that a lot of rigged meshes have only one LOD. + lod_factor *= LLVOVolume::sRiggedFactorMultiplier; distance = avatar->mDrawable->mDistanceWRTCamera; - radius = avatar->getBinRadius(); + F32 avatar_radius = avatar->getBinRadius(); + F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + radius = object_radius * LLVOVolume::sRiggedFactorMultiplier; + radius = llmin(radius, avatar_radius); } else { distance = mDrawable->mDistanceWRTCamera; radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); } - + //hold onto unmodified distance for debugging //F32 debug_distance = distance; - + distance *= sDistanceFactor; - F32 rampDist = LLVOVolume::sLODFactor * 2; - + F32 rampDist = lod_factor * 2; + if (distance < rampDist) { // Boost LOD when you're REALLY close @@ -1279,7 +1286,8 @@ BOOL LLVOVolume::calcLOD() distance *= F_PI/3.f; cur_detail = computeLODDetail(ll_round(distance, 0.01f), - ll_round(radius, 0.01f)); + ll_round(radius, 0.01f), + lod_factor); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a331908320..ca9917069b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -327,7 +327,7 @@ public: void clearRiggedVolume(); protected: - S32 computeLODDetail(F32 distance, F32 radius); + S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); @@ -379,6 +379,7 @@ private: public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop static F32 sLODFactor; // LOD scale factor + static F32 sRiggedFactorMultiplier; // Worn rigged LOD scale factor multiplier static F32 sDistanceFactor; // LOD distance factor static LLPointer sObjectMediaClient; -- cgit v1.2.3 From cd47f86c4ab6dd2bdeb98db06acd64d02cdff96f Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Tue, 19 Jul 2016 12:42:49 -0700 Subject: MAINT-6578 Add back Y Flip into QuickTime plugin used in OS X to match viewer setting --- indra/media_plugins/quicktime/media_plugin_quicktime.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 6d4c6ca43d..893fb738ce 100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -311,9 +311,7 @@ private: MatrixRecord transform; SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix double scaleX = (double) mWidth / mNaturalWidth; - - // 2016-05-31 CP remove local flip (via -1.0) since texture coods for media on a prim are now flipped for VLC/CEF - double scaleY = 1.0 * (double) mHeight / mNaturalHeight; + double scaleY = -1.0 * (double) mHeight / mNaturalHeight; double centerX = mWidth / 2.0; double centerY = mHeight / 2.0; ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); -- cgit v1.2.3 From 3ea324c1c47dc19f6d6dee813afe498b521010e2 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Wed, 20 Jul 2016 11:47:08 -0700 Subject: MAINT=6585: migrate from local python libraries to canonical llbase --- indra/llcorehttp/tests/test_llcorehttp_peer.py | 2 +- indra/llmessage/tests/test_llsdmessage_peer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 04cde651c4..5a059e53ca 100755 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -45,7 +45,7 @@ from SocketServer import ThreadingMixIn mydir = os.path.dirname(__file__) # expected to be .../indra/llcorehttp/tests/ sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse -from indra.base import llsd +from llbase import llsd from testrunner import freeport, run, debug, VERBOSE class TestHTTPRequestHandler(BaseHTTPRequestHandler): diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index e45249b1cb..485a125af0 100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -37,7 +37,7 @@ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/ sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse -from indra.base import llsd +from llbase import llsd from testrunner import freeport, run, debug, VERBOSE import time -- cgit v1.2.3 From d7636753e8a0ab021ea11f2a7369d9e488b3f2b4 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Wed, 20 Jul 2016 13:51:58 -0700 Subject: MAINT=6585: hg rm everything we don't need --- indra/lib/python/indra/__init__.py | 25 - indra/lib/python/indra/base/__init__.py | 27 - indra/lib/python/indra/base/cllsd_test.py | 73 -- indra/lib/python/indra/base/config.py | 266 ----- indra/lib/python/indra/base/llsd.py | 1052 -------------------- indra/lib/python/indra/base/lluuid.py | 319 ------ indra/lib/python/indra/base/metrics.py | 121 --- indra/lib/python/indra/ipc/__init__.py | 27 - indra/lib/python/indra/ipc/compatibility.py | 123 --- indra/lib/python/indra/ipc/httputil.py | 30 - indra/lib/python/indra/ipc/llmessage.py | 372 ------- indra/lib/python/indra/ipc/llsdhttp.py | 100 -- indra/lib/python/indra/ipc/mysql_pool.py | 81 -- indra/lib/python/indra/ipc/russ.py | 165 --- indra/lib/python/indra/ipc/servicebuilder.py | 134 --- indra/lib/python/indra/ipc/siesta.py | 468 --------- indra/lib/python/indra/ipc/siesta_test.py | 235 ----- indra/lib/python/indra/ipc/tokenstream.py | 154 --- indra/lib/python/indra/ipc/webdav.py | 597 ----------- indra/lib/python/indra/ipc/xml_rpc.py | 273 ----- indra/lib/python/indra/util/fastest_elementtree.py | 64 -- indra/lib/python/indra/util/helpformatter.py | 52 - indra/lib/python/indra/util/iterators.py | 63 -- indra/lib/python/indra/util/iterators_test.py | 72 -- indra/lib/python/indra/util/llperformance.py | 182 ---- indra/lib/python/indra/util/llsubprocess.py | 117 --- indra/lib/python/indra/util/named_query.py | 592 ----------- indra/lib/python/indra/util/shutil2.py | 84 -- .../python/indra/util/simperf_host_xml_parser.py | 338 ------- .../python/indra/util/simperf_oprof_interface.py | 167 ---- .../python/indra/util/simperf_proc_interface.py | 191 ---- indra/lib/python/indra/util/term.py | 222 ----- indra/lib/python/uuid.py | 508 ---------- 33 files changed, 7294 deletions(-) delete mode 100755 indra/lib/python/indra/__init__.py delete mode 100755 indra/lib/python/indra/base/__init__.py delete mode 100755 indra/lib/python/indra/base/cllsd_test.py delete mode 100755 indra/lib/python/indra/base/config.py delete mode 100755 indra/lib/python/indra/base/llsd.py delete mode 100755 indra/lib/python/indra/base/lluuid.py delete mode 100755 indra/lib/python/indra/base/metrics.py delete mode 100755 indra/lib/python/indra/ipc/__init__.py delete mode 100755 indra/lib/python/indra/ipc/compatibility.py delete mode 100755 indra/lib/python/indra/ipc/httputil.py delete mode 100755 indra/lib/python/indra/ipc/llmessage.py delete mode 100755 indra/lib/python/indra/ipc/llsdhttp.py delete mode 100755 indra/lib/python/indra/ipc/mysql_pool.py delete mode 100755 indra/lib/python/indra/ipc/russ.py delete mode 100755 indra/lib/python/indra/ipc/servicebuilder.py delete mode 100755 indra/lib/python/indra/ipc/siesta.py delete mode 100755 indra/lib/python/indra/ipc/siesta_test.py delete mode 100755 indra/lib/python/indra/ipc/tokenstream.py delete mode 100755 indra/lib/python/indra/ipc/webdav.py delete mode 100755 indra/lib/python/indra/ipc/xml_rpc.py delete mode 100755 indra/lib/python/indra/util/fastest_elementtree.py delete mode 100755 indra/lib/python/indra/util/helpformatter.py delete mode 100755 indra/lib/python/indra/util/iterators.py delete mode 100755 indra/lib/python/indra/util/iterators_test.py delete mode 100755 indra/lib/python/indra/util/llperformance.py delete mode 100755 indra/lib/python/indra/util/llsubprocess.py delete mode 100755 indra/lib/python/indra/util/named_query.py delete mode 100755 indra/lib/python/indra/util/shutil2.py delete mode 100755 indra/lib/python/indra/util/simperf_host_xml_parser.py delete mode 100755 indra/lib/python/indra/util/simperf_oprof_interface.py delete mode 100755 indra/lib/python/indra/util/simperf_proc_interface.py delete mode 100755 indra/lib/python/indra/util/term.py delete mode 100755 indra/lib/python/uuid.py (limited to 'indra') diff --git a/indra/lib/python/indra/__init__.py b/indra/lib/python/indra/__init__.py deleted file mode 100755 index 0c5053cf49..0000000000 --- a/indra/lib/python/indra/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -"""\ -@file __init__.py -@brief Initialization file for the indra module. - -$LicenseInfo:firstyear=2006&license=viewerlgpl$ -Second Life Viewer Source Code -Copyright (C) 2006-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$ -""" diff --git a/indra/lib/python/indra/base/__init__.py b/indra/lib/python/indra/base/__init__.py deleted file mode 100755 index 2904fd3380..0000000000 --- a/indra/lib/python/indra/base/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -"""\ -@file __init__.py -@brief Initialization file for the indra.base module. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" diff --git a/indra/lib/python/indra/base/cllsd_test.py b/indra/lib/python/indra/base/cllsd_test.py deleted file mode 100755 index 1f06898ffd..0000000000 --- a/indra/lib/python/indra/base/cllsd_test.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python -## -## $LicenseInfo:firstyear=2011&license=viewerlgpl$ -## Second Life Viewer Source Code -## Copyright (C) 2011, 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$ -from indra.base import llsd, lluuid -from datetime import datetime -import cllsd -import time, sys - -class myint(int): - pass - -values = ( - '&<>', - u'\u81acj', - llsd.uri('http://foo<'), - lluuid.UUID(), - llsd.LLSD(['thing']), - 1, - myint(31337), - sys.maxint + 10, - llsd.binary('foo'), - [], - {}, - {u'f&\u1212': 3}, - 3.1, - True, - None, - datetime.fromtimestamp(time.time()), - ) - -def valuator(values): - for v in values: - yield v - -longvalues = () # (values, list(values), iter(values), valuator(values)) - -for v in values + longvalues: - print '%r => %r' % (v, cllsd.llsd_to_xml(v)) - -a = [[{'a':3}]] * 1000000 - -s = time.time() -print hash(cllsd.llsd_to_xml(a)) -e = time.time() -t1 = e - s -print t1 - -s = time.time() -print hash(llsd.LLSDXMLFormatter()._format(a)) -e = time.time() -t2 = e - s -print t2 - -print 'Speedup:', t2 / t1 diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py deleted file mode 100755 index adafa29b51..0000000000 --- a/indra/lib/python/indra/base/config.py +++ /dev/null @@ -1,266 +0,0 @@ -"""\ -@file config.py -@brief Utility module for parsing and accessing the indra.xml config file. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import copy -import errno -import os -import traceback -import time -import types - -from os.path import dirname, getmtime, join, realpath -from indra.base import llsd - -_g_config = None - -class IndraConfig(object): - """ - IndraConfig loads a 'indra' xml configuration file - and loads into memory. This representation in memory - can get updated to overwrite values or add new values. - - The xml configuration file is considered a live file and changes - to the file are checked and reloaded periodically. If a value had - been overwritten via the update or set method, the loaded values - from the file are ignored (the values from the update/set methods - override) - """ - def __init__(self, indra_config_file): - self._indra_config_file = indra_config_file - self._reload_check_interval = 30 # seconds - self._last_check_time = 0 - self._last_mod_time = 0 - - self._config_overrides = {} - self._config_file_dict = {} - self._combined_dict = {} - - self._load() - - def _load(self): - # if you initialize the IndraConfig with None, no attempt - # is made to load any files - if self._indra_config_file is None: - return - - config_file = open(self._indra_config_file) - self._config_file_dict = llsd.parse(config_file.read()) - self._combine_dictionaries() - config_file.close() - - self._last_mod_time = self._get_last_modified_time() - self._last_check_time = time.time() # now - - def _get_last_modified_time(self): - """ - Returns the mtime (last modified time) of the config file, - if such exists. - """ - if self._indra_config_file is not None: - return os.path.getmtime(self._indra_config_file) - - return 0 - - def _combine_dictionaries(self): - self._combined_dict = {} - self._combined_dict.update(self._config_file_dict) - self._combined_dict.update(self._config_overrides) - - def _reload_if_necessary(self): - now = time.time() - - if (now - self._last_check_time) > self._reload_check_interval: - self._last_check_time = now - try: - modtime = self._get_last_modified_time() - if modtime > self._last_mod_time: - self._load() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - # someone messed with our internal state - # or removed the file - - print 'WARNING: Configuration file has been removed ' + (self._indra_config_file) - print 'Disabling reloading of configuration file.' - - traceback.print_exc() - - self._indra_config_file = None - self._last_check_time = 0 - self._last_mod_time = 0 - else: - raise # pass the exception along to the caller - - def __getitem__(self, key): - self._reload_if_necessary() - - return self._combined_dict[key] - - def get(self, key, default = None): - try: - return self.__getitem__(key) - except KeyError: - return default - - def __setitem__(self, key, value): - """ - Sets the value of the config setting of key to be newval - - Once any key/value pair is changed via the set method, - that key/value pair will remain set with that value until - change via the update or set method - """ - self._config_overrides[key] = value - self._combine_dictionaries() - - def set(self, key, newval): - return self.__setitem__(key, newval) - - def update(self, new_conf): - """ - Load an XML file and apply its map as overrides or additions - to the existing config. Update can be a file or a dict. - - Once any key/value pair is changed via the update method, - that key/value pair will remain set with that value until - change via the update or set method - """ - if isinstance(new_conf, dict): - overrides = new_conf - else: - # assuming that it is a filename - config_file = open(new_conf) - overrides = llsd.parse(config_file.read()) - config_file.close() - - self._config_overrides.update(overrides) - self._combine_dictionaries() - - def as_dict(self): - """ - Returns immutable copy of the IndraConfig as a dictionary - """ - return copy.deepcopy(self._combined_dict) - -def load(config_xml_file = None): - global _g_config - - load_default_files = config_xml_file is None - if load_default_files: - ## going from: - ## "/opt/linden/indra/lib/python/indra/base/config.py" - ## to: - ## "/opt/linden/etc/indra.xml" - config_xml_file = realpath( - dirname(realpath(__file__)) + "../../../../../../etc/indra.xml") - - try: - _g_config = IndraConfig(config_xml_file) - except IOError: - # Failure to load passed in file - # or indra.xml default file - if load_default_files: - try: - config_xml_file = realpath( - dirname(realpath(__file__)) + "../../../../../../etc/globals.xml") - _g_config = IndraConfig(config_xml_file) - return - except IOError: - # Failure to load globals.xml - # fall to code below - pass - - # Either failed to load passed in file - # or failed to load all default files - _g_config = IndraConfig(None) - -def dump(indra_xml_file, indra_cfg = None, update_in_mem=False): - ''' - Dump config contents into a file - Kindof reverse of load. - Optionally takes a new config to dump. - Does NOT update global config unless requested. - ''' - global _g_config - - if not indra_cfg: - if _g_config is None: - return - - indra_cfg = _g_config.as_dict() - - if not indra_cfg: - return - - config_file = open(indra_xml_file, 'w') - _config_xml = llsd.format_xml(indra_cfg) - config_file.write(_config_xml) - config_file.close() - - if update_in_mem: - update(indra_cfg) - -def update(new_conf): - global _g_config - - if _g_config is None: - # To keep with how this function behaved - # previously, a call to update - # before the global is defined - # make a new global config which does not - # load data from a file. - _g_config = IndraConfig(None) - - return _g_config.update(new_conf) - -def get(key, default = None): - global _g_config - - if _g_config is None: - load() - - return _g_config.get(key, default) - -def set(key, newval): - """ - Sets the value of the config setting of key to be newval - - Once any key/value pair is changed via the set method, - that key/value pair will remain set with that value until - change via the update or set method or program termination - """ - global _g_config - - if _g_config is None: - _g_config = IndraConfig(None) - - _g_config.set(key, newval) - -def get_config(): - global _g_config - return _g_config diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py deleted file mode 100755 index 4527b115f9..0000000000 --- a/indra/lib/python/indra/base/llsd.py +++ /dev/null @@ -1,1052 +0,0 @@ -"""\ -@file llsd.py -@brief Types as well as parsing and formatting functions for handling LLSD. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import datetime -import base64 -import string -import struct -import time -import types -import re - -from indra.util.fastest_elementtree import ElementTreeError, fromstring -from indra.base import lluuid - -# cllsd.c in server/server-1.25 has memory leaks, -# so disabling cllsd for now -#try: -# import cllsd -#except ImportError: -# cllsd = None -cllsd = None - -int_regex = re.compile(r"[-+]?\d+") -real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?") -alpha_regex = re.compile(r"[a-zA-Z]+") -date_regex = re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})T" - r"(?P\d{2}):(?P\d{2}):(?P\d{2})" - r"(?P(\.\d+)?)Z") -#date: d"YYYY-MM-DDTHH:MM:SS.FFFFFFZ" - -class LLSDParseError(Exception): - pass - -class LLSDSerializationError(TypeError): - pass - - -class binary(str): - pass - -class uri(str): - pass - - -BOOL_TRUE = ('1', '1.0', 'true') -BOOL_FALSE = ('0', '0.0', 'false', '') - - -def format_datestr(v): - """ Formats a datetime or date object into the string format shared by xml and notation serializations.""" - if hasattr(v, 'microsecond'): - return v.isoformat() + 'Z' - else: - return v.strftime('%Y-%m-%dT%H:%M:%SZ') - -def parse_datestr(datestr): - """Parses a datetime object from the string format shared by xml and notation serializations.""" - if datestr == "": - return datetime.datetime(1970, 1, 1) - - match = re.match(date_regex, datestr) - if not match: - raise LLSDParseError("invalid date string '%s'." % datestr) - - year = int(match.group('year')) - month = int(match.group('month')) - day = int(match.group('day')) - hour = int(match.group('hour')) - minute = int(match.group('minute')) - second = int(match.group('second')) - seconds_float = match.group('second_float') - microsecond = 0 - if seconds_float: - microsecond = int(float('0' + seconds_float) * 1e6) - return datetime.datetime(year, month, day, hour, minute, second, microsecond) - - -def bool_to_python(node): - val = node.text or '' - if val in BOOL_TRUE: - return True - else: - return False - -def int_to_python(node): - val = node.text or '' - if not val.strip(): - return 0 - return int(val) - -def real_to_python(node): - val = node.text or '' - if not val.strip(): - return 0.0 - return float(val) - -def uuid_to_python(node): - return lluuid.UUID(node.text) - -def str_to_python(node): - return node.text or '' - -def bin_to_python(node): - return binary(base64.decodestring(node.text or '')) - -def date_to_python(node): - val = node.text or '' - if not val: - val = "1970-01-01T00:00:00Z" - return parse_datestr(val) - - -def uri_to_python(node): - val = node.text or '' - if not val: - return None - return uri(val) - -def map_to_python(node): - result = {} - for index in range(len(node))[::2]: - result[node[index].text] = to_python(node[index+1]) - return result - -def array_to_python(node): - return [to_python(child) for child in node] - - -NODE_HANDLERS = dict( - undef=lambda x: None, - boolean=bool_to_python, - integer=int_to_python, - real=real_to_python, - uuid=uuid_to_python, - string=str_to_python, - binary=bin_to_python, - date=date_to_python, - uri=uri_to_python, - map=map_to_python, - array=array_to_python, - ) - -def to_python(node): - return NODE_HANDLERS[node.tag](node) - -class Nothing(object): - pass - - -class LLSDXMLFormatter(object): - def __init__(self): - self.type_map = { - type(None) : self.UNDEF, - bool : self.BOOLEAN, - int : self.INTEGER, - long : self.INTEGER, - float : self.REAL, - lluuid.UUID : self.UUID, - binary : self.BINARY, - str : self.STRING, - unicode : self.STRING, - uri : self.URI, - datetime.datetime : self.DATE, - datetime.date : self.DATE, - list : self.ARRAY, - tuple : self.ARRAY, - types.GeneratorType : self.ARRAY, - dict : self.MAP, - LLSD : self.LLSD - } - - def elt(self, name, contents=None): - if(contents is None or contents is ''): - return "<%s />" % (name,) - else: - if type(contents) is unicode: - contents = contents.encode('utf-8') - return "<%s>%s" % (name, contents, name) - - def xml_esc(self, v): - if type(v) is unicode: - v = v.encode('utf-8') - return v.replace('&', '&').replace('<', '<').replace('>', '>') - - def LLSD(self, v): - return self.generate(v.thing) - def UNDEF(self, v): - return self.elt('undef') - def BOOLEAN(self, v): - if v: - return self.elt('boolean', 'true') - else: - return self.elt('boolean', 'false') - def INTEGER(self, v): - return self.elt('integer', v) - def REAL(self, v): - return self.elt('real', v) - def UUID(self, v): - if(v.isNull()): - return self.elt('uuid') - else: - return self.elt('uuid', v) - def BINARY(self, v): - return self.elt('binary', base64.encodestring(v)) - def STRING(self, v): - return self.elt('string', self.xml_esc(v)) - def URI(self, v): - return self.elt('uri', self.xml_esc(str(v))) - def DATE(self, v): - return self.elt('date', format_datestr(v)) - def ARRAY(self, v): - return self.elt('array', ''.join([self.generate(item) for item in v])) - def MAP(self, v): - return self.elt( - 'map', - ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value)) - for key, value in v.items()])) - - typeof = type - def generate(self, something): - t = self.typeof(something) - if self.type_map.has_key(t): - return self.type_map[t](something) - else: - raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % ( - t, something)) - - def _format(self, something): - return '' + self.elt("llsd", self.generate(something)) - - def format(self, something): - if cllsd: - return cllsd.llsd_to_xml(something) - return self._format(something) - -_g_xml_formatter = None -def format_xml(something): - global _g_xml_formatter - if _g_xml_formatter is None: - _g_xml_formatter = LLSDXMLFormatter() - return _g_xml_formatter.format(something) - -class LLSDXMLPrettyFormatter(LLSDXMLFormatter): - def __init__(self, indent_atom = None): - # Call the super class constructor so that we have the type map - super(LLSDXMLPrettyFormatter, self).__init__() - - # Override the type map to use our specialized formatters to - # emit the pretty output. - self.type_map[list] = self.PRETTY_ARRAY - self.type_map[tuple] = self.PRETTY_ARRAY - self.type_map[types.GeneratorType] = self.PRETTY_ARRAY, - self.type_map[dict] = self.PRETTY_MAP - - # Private data used for indentation. - self._indent_level = 1 - if indent_atom is None: - self._indent_atom = ' ' - else: - self._indent_atom = indent_atom - - def _indent(self): - "Return an indentation based on the atom and indentation level." - return self._indent_atom * self._indent_level - - def PRETTY_ARRAY(self, v): - rv = [] - rv.append('\n') - self._indent_level = self._indent_level + 1 - rv.extend(["%s%s\n" % - (self._indent(), - self.generate(item)) - for item in v]) - self._indent_level = self._indent_level - 1 - rv.append(self._indent()) - rv.append('') - return ''.join(rv) - - def PRETTY_MAP(self, v): - rv = [] - rv.append('\n') - self._indent_level = self._indent_level + 1 - keys = v.keys() - keys.sort() - rv.extend(["%s%s\n%s%s\n" % - (self._indent(), - self.elt('key', key), - self._indent(), - self.generate(v[key])) - for key in keys]) - self._indent_level = self._indent_level - 1 - rv.append(self._indent()) - rv.append('') - return ''.join(rv) - - def format(self, something): - data = [] - data.append('\n') - data.append(self.generate(something)) - data.append('\n') - return '\n'.join(data) - -def format_pretty_xml(something): - """@brief Serialize a python object as 'pretty' llsd xml. - - The output conforms to the LLSD DTD, unlike the output from the - standard python xml.dom DOM::toprettyxml() method which does not - preserve significant whitespace. - This function is not necessarily suited for serializing very large - objects. It is not optimized by the cllsd module, and sorts on - dict (llsd map) keys alphabetically to ease human reading. - """ - return LLSDXMLPrettyFormatter().format(something) - -class LLSDNotationFormatter(object): - def __init__(self): - self.type_map = { - type(None) : self.UNDEF, - bool : self.BOOLEAN, - int : self.INTEGER, - long : self.INTEGER, - float : self.REAL, - lluuid.UUID : self.UUID, - binary : self.BINARY, - str : self.STRING, - unicode : self.STRING, - uri : self.URI, - datetime.datetime : self.DATE, - datetime.date : self.DATE, - list : self.ARRAY, - tuple : self.ARRAY, - types.GeneratorType : self.ARRAY, - dict : self.MAP, - LLSD : self.LLSD - } - - def LLSD(self, v): - return self.generate(v.thing) - def UNDEF(self, v): - return '!' - def BOOLEAN(self, v): - if v: - return 'true' - else: - return 'false' - def INTEGER(self, v): - return "i%s" % v - def REAL(self, v): - return "r%s" % v - def UUID(self, v): - return "u%s" % v - def BINARY(self, v): - return 'b64"' + base64.encodestring(v) + '"' - def STRING(self, v): - if isinstance(v, unicode): - v = v.encode('utf-8') - return "'%s'" % v.replace("\\", "\\\\").replace("'", "\\'") - def URI(self, v): - return 'l"%s"' % str(v).replace("\\", "\\\\").replace('"', '\\"') - def DATE(self, v): - return 'd"%s"' % format_datestr(v) - def ARRAY(self, v): - return "[%s]" % ','.join([self.generate(item) for item in v]) - def MAP(self, v): - def fix(key): - if isinstance(key, unicode): - return key.encode('utf-8') - return key - return "{%s}" % ','.join(["'%s':%s" % (fix(key).replace("\\", "\\\\").replace("'", "\\'"), self.generate(value)) - for key, value in v.items()]) - - def generate(self, something): - t = type(something) - handler = self.type_map.get(t) - if handler: - return handler(something) - else: - try: - return self.ARRAY(iter(something)) - except TypeError: - raise LLSDSerializationError( - "Cannot serialize unknown type: %s (%s)" % (t, something)) - - def format(self, something): - return self.generate(something) - -def format_notation(something): - return LLSDNotationFormatter().format(something) - -def _hex_as_nybble(hex): - if (hex >= '0') and (hex <= '9'): - return ord(hex) - ord('0') - elif (hex >= 'a') and (hex <='f'): - return 10 + ord(hex) - ord('a') - elif (hex >= 'A') and (hex <='F'): - return 10 + ord(hex) - ord('A'); - -class LLSDBinaryParser(object): - def __init__(self): - pass - - def parse(self, buffer, ignore_binary = False): - """ - This is the basic public interface for parsing. - - @param buffer the binary data to parse in an indexable sequence. - @param ignore_binary parser throws away data in llsd binary nodes. - @return returns a python object. - """ - self._buffer = buffer - self._index = 0 - self._keep_binary = not ignore_binary - return self._parse() - - def _parse(self): - cc = self._buffer[self._index] - self._index += 1 - if cc == '{': - return self._parse_map() - elif cc == '[': - return self._parse_array() - elif cc == '!': - return None - elif cc == '0': - return False - elif cc == '1': - return True - elif cc == 'i': - # 'i' = integer - idx = self._index - self._index += 4 - return struct.unpack("!i", self._buffer[idx:idx+4])[0] - elif cc == ('r'): - # 'r' = real number - idx = self._index - self._index += 8 - return struct.unpack("!d", self._buffer[idx:idx+8])[0] - elif cc == 'u': - # 'u' = uuid - idx = self._index - self._index += 16 - return lluuid.uuid_bits_to_uuid(self._buffer[idx:idx+16]) - elif cc == 's': - # 's' = string - return self._parse_string() - elif cc in ("'", '"'): - # delimited/escaped string - return self._parse_string_delim(cc) - elif cc == 'l': - # 'l' = uri - return uri(self._parse_string()) - elif cc == ('d'): - # 'd' = date in seconds since epoch - idx = self._index - self._index += 8 - seconds = struct.unpack("!d", self._buffer[idx:idx+8])[0] - return datetime.datetime.fromtimestamp(seconds) - elif cc == 'b': - binary = self._parse_string() - if self._keep_binary: - return binary - # *NOTE: maybe have a binary placeholder which has the - # length. - return None - else: - raise LLSDParseError("invalid binary token at byte %d: %d" % ( - self._index - 1, ord(cc))) - - def _parse_map(self): - rv = {} - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - count = 0 - cc = self._buffer[self._index] - self._index += 1 - key = '' - while (cc != '}') and (count < size): - if cc == 'k': - key = self._parse_string() - elif cc in ("'", '"'): - key = self._parse_string_delim(cc) - else: - raise LLSDParseError("invalid map key at byte %d." % ( - self._index - 1,)) - value = self._parse() - rv[key] = value - count += 1 - cc = self._buffer[self._index] - self._index += 1 - if cc != '}': - raise LLSDParseError("invalid map close token at byte %d." % ( - self._index,)) - return rv - - def _parse_array(self): - rv = [] - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - count = 0 - cc = self._buffer[self._index] - while (cc != ']') and (count < size): - rv.append(self._parse()) - count += 1 - cc = self._buffer[self._index] - if cc != ']': - raise LLSDParseError("invalid array close token at byte %d." % ( - self._index,)) - self._index += 1 - return rv - - def _parse_string(self): - size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0] - self._index += 4 - rv = self._buffer[self._index:self._index+size] - self._index += size - return rv - - def _parse_string_delim(self, delim): - list = [] - found_escape = False - found_hex = False - found_digit = False - byte = 0 - while True: - cc = self._buffer[self._index] - self._index += 1 - if found_escape: - if found_hex: - if found_digit: - found_escape = False - found_hex = False - found_digit = False - byte <<= 4 - byte |= _hex_as_nybble(cc) - list.append(chr(byte)) - byte = 0 - else: - found_digit = True - byte = _hex_as_nybble(cc) - elif cc == 'x': - found_hex = True - else: - if cc == 'a': - list.append('\a') - elif cc == 'b': - list.append('\b') - elif cc == 'f': - list.append('\f') - elif cc == 'n': - list.append('\n') - elif cc == 'r': - list.append('\r') - elif cc == 't': - list.append('\t') - elif cc == 'v': - list.append('\v') - else: - list.append(cc) - found_escape = False - elif cc == '\\': - found_escape = True - elif cc == delim: - break - else: - list.append(cc) - return ''.join(list) - -class LLSDNotationParser(object): - """ Parse LLSD notation: - map: { string:object, string:object } - array: [ object, object, object ] - undef: ! - boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE - integer: i#### - real: r#### - uuid: u#### - string: "g\'day" | 'have a "nice" day' | s(size)"raw data" - uri: l"escaped" - date: d"YYYY-MM-DDTHH:MM:SS.FFZ" - binary: b##"ff3120ab1" | b(size)"raw data" - """ - def __init__(self): - pass - - def parse(self, buffer, ignore_binary = False): - """ - This is the basic public interface for parsing. - - @param buffer the notation string to parse. - @param ignore_binary parser throws away data in llsd binary nodes. - @return returns a python object. - """ - if buffer == "": - return False - - self._buffer = buffer - self._index = 0 - return self._parse() - - def _parse(self): - cc = self._buffer[self._index] - self._index += 1 - if cc == '{': - return self._parse_map() - elif cc == '[': - return self._parse_array() - elif cc == '!': - return None - elif cc == '0': - return False - elif cc == '1': - return True - elif cc in ('F', 'f'): - self._skip_alpha() - return False - elif cc in ('T', 't'): - self._skip_alpha() - return True - elif cc == 'i': - # 'i' = integer - return self._parse_integer() - elif cc == ('r'): - # 'r' = real number - return self._parse_real() - elif cc == 'u': - # 'u' = uuid - return self._parse_uuid() - elif cc in ("'", '"', 's'): - return self._parse_string(cc) - elif cc == 'l': - # 'l' = uri - delim = self._buffer[self._index] - self._index += 1 - val = uri(self._parse_string(delim)) - if len(val) == 0: - return None - return val - elif cc == ('d'): - # 'd' = date in seconds since epoch - return self._parse_date() - elif cc == 'b': - return self._parse_binary() - else: - raise LLSDParseError("invalid token at index %d: %d" % ( - self._index - 1, ord(cc))) - - def _parse_binary(self): - i = self._index - if self._buffer[i:i+2] == '64': - q = self._buffer[i+2] - e = self._buffer.find(q, i+3) - try: - return base64.decodestring(self._buffer[i+3:e]) - finally: - self._index = e + 1 - else: - raise LLSDParseError('random horrible binary format not supported') - - def _parse_map(self): - """ map: { string:object, string:object } """ - rv = {} - cc = self._buffer[self._index] - self._index += 1 - key = '' - found_key = False - while (cc != '}'): - if not found_key: - if cc in ("'", '"', 's'): - key = self._parse_string(cc) - found_key = True - elif cc.isspace() or cc == ',': - cc = self._buffer[self._index] - self._index += 1 - else: - raise LLSDParseError("invalid map key at byte %d." % ( - self._index - 1,)) - elif cc.isspace() or cc == ':': - cc = self._buffer[self._index] - self._index += 1 - continue - else: - self._index += 1 - value = self._parse() - rv[key] = value - found_key = False - cc = self._buffer[self._index] - self._index += 1 - - return rv - - def _parse_array(self): - """ array: [ object, object, object ] """ - rv = [] - cc = self._buffer[self._index] - while (cc != ']'): - if cc.isspace() or cc == ',': - self._index += 1 - cc = self._buffer[self._index] - continue - rv.append(self._parse()) - cc = self._buffer[self._index] - - if cc != ']': - raise LLSDParseError("invalid array close token at index %d." % ( - self._index,)) - self._index += 1 - return rv - - def _parse_uuid(self): - match = re.match(lluuid.UUID.uuid_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid uuid token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return lluuid.UUID(self._buffer[start:end]) - - def _skip_alpha(self): - match = re.match(alpha_regex, self._buffer[self._index:]) - if match: - self._index += match.end() - - def _parse_date(self): - delim = self._buffer[self._index] - self._index += 1 - datestr = self._parse_string(delim) - return parse_datestr(datestr) - - def _parse_real(self): - match = re.match(real_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid real token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return float( self._buffer[start:end] ) - - def _parse_integer(self): - match = re.match(int_regex, self._buffer[self._index:]) - if not match: - raise LLSDParseError("invalid integer token at index %d." % self._index) - - (start, end) = match.span() - start += self._index - end += self._index - self._index = end - return int( self._buffer[start:end] ) - - def _parse_string(self, delim): - """ string: "g\'day" | 'have a "nice" day' | s(size)"raw data" """ - rv = "" - - if delim in ("'", '"'): - rv = self._parse_string_delim(delim) - elif delim == 's': - rv = self._parse_string_raw() - else: - raise LLSDParseError("invalid string token at index %d." % self._index) - - return rv - - - def _parse_string_delim(self, delim): - """ string: "g'day 'un" | 'have a "nice" day' """ - list = [] - found_escape = False - found_hex = False - found_digit = False - byte = 0 - while True: - cc = self._buffer[self._index] - self._index += 1 - if found_escape: - if found_hex: - if found_digit: - found_escape = False - found_hex = False - found_digit = False - byte <<= 4 - byte |= _hex_as_nybble(cc) - list.append(chr(byte)) - byte = 0 - else: - found_digit = True - byte = _hex_as_nybble(cc) - elif cc == 'x': - found_hex = True - else: - if cc == 'a': - list.append('\a') - elif cc == 'b': - list.append('\b') - elif cc == 'f': - list.append('\f') - elif cc == 'n': - list.append('\n') - elif cc == 'r': - list.append('\r') - elif cc == 't': - list.append('\t') - elif cc == 'v': - list.append('\v') - else: - list.append(cc) - found_escape = False - elif cc == '\\': - found_escape = True - elif cc == delim: - break - else: - list.append(cc) - return ''.join(list) - - def _parse_string_raw(self): - """ string: s(size)"raw data" """ - # Read the (size) portion. - cc = self._buffer[self._index] - self._index += 1 - if cc != '(': - raise LLSDParseError("invalid string token at index %d." % self._index) - - rparen = self._buffer.find(')', self._index) - if rparen == -1: - raise LLSDParseError("invalid string token at index %d." % self._index) - - size = int(self._buffer[self._index:rparen]) - - self._index = rparen + 1 - delim = self._buffer[self._index] - self._index += 1 - if delim not in ("'", '"'): - raise LLSDParseError("invalid string token at index %d." % self._index) - - rv = self._buffer[self._index:(self._index + size)] - self._index += size - cc = self._buffer[self._index] - self._index += 1 - if cc != delim: - raise LLSDParseError("invalid string token at index %d." % self._index) - - return rv - -def format_binary(something): - return '\n' + _format_binary_recurse(something) - -def _format_binary_recurse(something): - def _format_list(something): - array_builder = [] - array_builder.append('[' + struct.pack('!i', len(something))) - for item in something: - array_builder.append(_format_binary_recurse(item)) - array_builder.append(']') - return ''.join(array_builder) - - if something is None: - return '!' - elif isinstance(something, LLSD): - return _format_binary_recurse(something.thing) - elif isinstance(something, bool): - if something: - return '1' - else: - return '0' - elif isinstance(something, (int, long)): - return 'i' + struct.pack('!i', something) - elif isinstance(something, float): - return 'r' + struct.pack('!d', something) - elif isinstance(something, lluuid.UUID): - return 'u' + something._bits - elif isinstance(something, binary): - return 'b' + struct.pack('!i', len(something)) + something - elif isinstance(something, str): - return 's' + struct.pack('!i', len(something)) + something - elif isinstance(something, unicode): - something = something.encode('utf-8') - return 's' + struct.pack('!i', len(something)) + something - elif isinstance(something, uri): - return 'l' + struct.pack('!i', len(something)) + something - elif isinstance(something, datetime.datetime): - seconds_since_epoch = time.mktime(something.timetuple()) - return 'd' + struct.pack('!d', seconds_since_epoch) - elif isinstance(something, (list, tuple)): - return _format_list(something) - elif isinstance(something, dict): - map_builder = [] - map_builder.append('{' + struct.pack('!i', len(something))) - for key, value in something.items(): - if isinstance(key, unicode): - key = key.encode('utf-8') - map_builder.append('k' + struct.pack('!i', len(key)) + key) - map_builder.append(_format_binary_recurse(value)) - map_builder.append('}') - return ''.join(map_builder) - else: - try: - return _format_list(list(something)) - except TypeError: - raise LLSDSerializationError( - "Cannot serialize unknown type: %s (%s)" % - (type(something), something)) - - -def parse_binary(binary): - if binary.startswith(''): - just_binary = binary.split('\n', 1)[1] - else: - just_binary = binary - return LLSDBinaryParser().parse(just_binary) - -def parse_xml(something): - try: - return to_python(fromstring(something)[0]) - except ElementTreeError, err: - raise LLSDParseError(*err.args) - -def parse_notation(something): - return LLSDNotationParser().parse(something) - -def parse(something): - try: - something = string.lstrip(something) #remove any pre-trailing whitespace - if something.startswith(''): - return parse_binary(something) - # This should be better. - elif something.startswith('<'): - return parse_xml(something) - else: - return parse_notation(something) - except KeyError, e: - raise Exception('LLSD could not be parsed: %s' % (e,)) - -class LLSD(object): - def __init__(self, thing=None): - self.thing = thing - - def __str__(self): - return self.toXML(self.thing) - - parse = staticmethod(parse) - toXML = staticmethod(format_xml) - toPrettyXML = staticmethod(format_pretty_xml) - toBinary = staticmethod(format_binary) - toNotation = staticmethod(format_notation) - - -undef = LLSD(None) - -XML_MIME_TYPE = 'application/llsd+xml' -BINARY_MIME_TYPE = 'application/llsd+binary' - -# register converters for llsd in mulib, if it is available -try: - from mulib import stacked, mu - stacked.NoProducer() # just to exercise stacked - mu.safe_load(None) # just to exercise mu -except: - # mulib not available, don't print an error message since this is normal - pass -else: - mu.add_parser(parse, XML_MIME_TYPE) - mu.add_parser(parse, 'application/llsd+binary') - - def llsd_convert_xml(llsd_stuff, request): - request.write(format_xml(llsd_stuff)) - - def llsd_convert_binary(llsd_stuff, request): - request.write(format_binary(llsd_stuff)) - - for typ in [LLSD, dict, list, tuple, str, int, long, float, bool, unicode, type(None)]: - stacked.add_producer(typ, llsd_convert_xml, XML_MIME_TYPE) - stacked.add_producer(typ, llsd_convert_xml, 'application/xml') - stacked.add_producer(typ, llsd_convert_xml, 'text/xml') - - stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary') - - stacked.add_producer(LLSD, llsd_convert_xml, '*/*') - - # in case someone is using the legacy mu.xml wrapper, we need to - # tell mu to produce application/xml or application/llsd+xml - # (based on the accept header) from raw xml. Phoenix 2008-07-21 - stacked.add_producer(mu.xml, mu.produce_raw, XML_MIME_TYPE) - stacked.add_producer(mu.xml, mu.produce_raw, 'application/xml') - - - -# mulib wsgi stuff -# try: -# from mulib import mu, adapters -# -# # try some known attributes from mulib to be ultra-sure we've imported it -# mu.get_current -# adapters.handlers -# except: -# # mulib not available, don't print an error message since this is normal -# pass -# else: -# def llsd_xml_handler(content_type): -# def handle_llsd_xml(env, start_response): -# llsd_stuff, _ = mu.get_current(env) -# result = format_xml(llsd_stuff) -# start_response("200 OK", [('Content-Type', content_type)]) -# env['mu.negotiated_type'] = content_type -# yield result -# return handle_llsd_xml -# -# def llsd_binary_handler(content_type): -# def handle_llsd_binary(env, start_response): -# llsd_stuff, _ = mu.get_current(env) -# result = format_binary(llsd_stuff) -# start_response("200 OK", [('Content-Type', content_type)]) -# env['mu.negotiated_type'] = content_type -# yield result -# return handle_llsd_binary -# -# adapters.DEFAULT_PARSERS[XML_MIME_TYPE] = parse - -# for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]: -# for content_type in (XML_MIME_TYPE, 'application/xml'): -# adapters.handlers.set_handler(typ, llsd_xml_handler(content_type), content_type) -# -# adapters.handlers.set_handler(typ, llsd_binary_handler(BINARY_MIME_TYPE), BINARY_MIME_TYPE) -# -# adapters.handlers.set_handler(LLSD, llsd_xml_handler(XML_MIME_TYPE), '*/*') diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py deleted file mode 100755 index 7413ffe10d..0000000000 --- a/indra/lib/python/indra/base/lluuid.py +++ /dev/null @@ -1,319 +0,0 @@ -"""\ -@file lluuid.py -@brief UUID parser/generator. - -$LicenseInfo:firstyear=2004&license=mit$ - -Copyright (c) 2004-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import random, socket, string, time, re -import uuid -try: - # Python 2.6 - from hashlib import md5 -except ImportError: - # Python 2.5 and earlier - from md5 import new as md5 - -def _int2binstr(i,l): - s='' - for a in range(l): - s=chr(i&0xFF)+s - i>>=8 - return s - -def _binstr2int(s): - i = long(0) - for c in s: - i = (i<<8) + ord(c) - return i - -class UUID(object): - """ - A class which represents a 16 byte integer. Stored as a 16 byte 8 - bit character string. - - The string version is to be of the form: - AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - - NULL_STR = "00000000-0000-0000-0000-000000000000" - - # the UUIDREGEX_STRING is helpful for parsing UUID's in text - hex_wildcard = r"[0-9a-fA-F]" - word = hex_wildcard + r"{4,4}-" - long_word = hex_wildcard + r"{8,8}-" - very_long_word = hex_wildcard + r"{12,12}" - UUID_REGEX_STRING = long_word + word + word + word + very_long_word - uuid_regex = re.compile(UUID_REGEX_STRING) - - rand = random.Random() - ip = '' - try: - ip = socket.gethostbyname(socket.gethostname()) - except(socket.gaierror, socket.error): - # no ip address, so just default to somewhere in 10.x.x.x - ip = '10' - for i in range(3): - ip += '.' + str(rand.randrange(1,254)) - hexip = ''.join(["%04x" % long(i) for i in ip.split('.')]) - lastid = '' - - def __init__(self, possible_uuid=None): - """ - Initialize to first valid UUID in argument (if a string), - or to null UUID if none found or argument is not supplied. - - If the argument is a UUID, the constructed object will be a copy of it. - """ - self._bits = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - if possible_uuid is None: - return - - if isinstance(possible_uuid, type(self)): - self.set(possible_uuid) - return - - uuid_match = UUID.uuid_regex.search(possible_uuid) - if uuid_match: - uuid_string = uuid_match.group() - s = string.replace(uuid_string, '-', '') - self._bits = _int2binstr(string.atol(s[:8],16),4) + \ - _int2binstr(string.atol(s[8:16],16),4) + \ - _int2binstr(string.atol(s[16:24],16),4) + \ - _int2binstr(string.atol(s[24:],16),4) - - def __len__(self): - """ - Used by the len() builtin. - """ - return 36 - - def __nonzero__(self): - return self._bits != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - - def __str__(self): - uuid_string = self.toString() - return uuid_string - - __repr__ = __str__ - - def __getitem__(self, index): - return str(self)[index] - - def __eq__(self, other): - if isinstance(other, (str, unicode)): - return other == str(self) - return self._bits == getattr(other, '_bits', '') - - def __ne__(self, other): - return not self.__eq__(other) - - def __le__(self, other): - return self._bits <= other._bits - - def __ge__(self, other): - return self._bits >= other._bits - - def __lt__(self, other): - return self._bits < other._bits - - def __gt__(self, other): - return self._bits > other._bits - - def __hash__(self): - return hash(self._bits) - - def set(self, uuid): - self._bits = uuid._bits - - def setFromString(self, uuid_string): - """ - Given a string version of a uuid, set self bits - appropriately. Returns self. - """ - s = string.replace(uuid_string, '-', '') - self._bits = _int2binstr(string.atol(s[:8],16),4) + \ - _int2binstr(string.atol(s[8:16],16),4) + \ - _int2binstr(string.atol(s[16:24],16),4) + \ - _int2binstr(string.atol(s[24:],16),4) - return self - - def setFromMemoryDump(self, gdb_string): - """ - We expect to get gdb_string as four hex units. eg: - 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 - Which will be translated to: - db547d14-1b3f4bc3-9b984f71-d22f890a - Returns self. - """ - s = string.replace(gdb_string, '0x', '') - s = string.replace(s, ' ', '') - t = '' - for i in range(8,40,8): - for j in range(0,8,2): - t = t + s[i-j-2:i-j] - self.setFromString(t) - - def toString(self): - """ - Return as a string matching the LL standard - AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - return uuid_bits_to_string(self._bits) - - def getAsString(self): - """ - Return a different string representation of the form - AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex) - where A=network address, B=timestamp, C=random. - """ - i1 = _binstr2int(self._bits[0:4]) - i2 = _binstr2int(self._bits[4:8]) - i3 = _binstr2int(self._bits[8:12]) - i4 = _binstr2int(self._bits[12:16]) - return '%08lx-%08lx-%08lx-%08lx' % (i1,i2,i3,i4) - - def generate(self): - """ - Generate a new uuid. This algorithm is slightly different - from c++ implementation for portability reasons. - Returns self. - """ - m = md5() - m.update(uuid.uuid1().bytes) - self._bits = m.digest() - return self - - def isNull(self): - """ - Returns 1 if the uuid is null - ie, equal to default uuid. - """ - return (self._bits == "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") - - def xor(self, rhs): - """ - xors self with rhs. - """ - v1 = _binstr2int(self._bits[0:4]) ^ _binstr2int(rhs._bits[0:4]) - v2 = _binstr2int(self._bits[4:8]) ^ _binstr2int(rhs._bits[4:8]) - v3 = _binstr2int(self._bits[8:12]) ^ _binstr2int(rhs._bits[8:12]) - v4 = _binstr2int(self._bits[12:16]) ^ _binstr2int(rhs._bits[12:16]) - self._bits = _int2binstr(v1,4) + \ - _int2binstr(v2,4) + \ - _int2binstr(v3,4) + \ - _int2binstr(v4,4) - - -# module-level null constant -NULL = UUID() - -def printTranslatedMemory(four_hex_uints): - """ - We expect to get the string as four hex units. eg: - 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 - Which will be translated to: - db547d14-1b3f4bc3-9b984f71-d22f890a - """ - uuid = UUID() - uuid.setFromMemoryDump(four_hex_uints) - print uuid.toString() - -def isUUID(id_str): - """ - This function returns: - - 1 if the string passed is a UUID - - 0 is the string passed is not a UUID - - None if it neither of the if's below is satisfied - """ - if not id_str or len(id_str) < 5 or len(id_str) > 36: - return 0 - - if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str): - return 1 - - return None - -def isPossiblyID(id_str): - """ - This function returns 1 if the string passed has some uuid-like - characteristics. Otherwise returns 0. - """ - - is_uuid = isUUID(id_str) - if is_uuid is not None: - return is_uuid - - # build a string which matches every character. - hex_wildcard = r"[0-9a-fA-F]" - chars = len(id_str) - next = min(chars, 8) - matcher = hex_wildcard+"{"+str(next)+","+str(next)+"}" - chars = chars - next - if chars > 0: - matcher = matcher + "-" - chars = chars - 1 - for block in range(3): - next = max(min(chars, 4), 0) - if next: - matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" - chars = chars - next - if chars > 0: - matcher = matcher + "-" - chars = chars - 1 - if chars > 0: - next = min(chars, 12) - matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" - #print matcher - uuid_matcher = re.compile(matcher) - if uuid_matcher.match(id_str): - return 1 - return 0 - -def uuid_bits_to_string(bits): - i1 = _binstr2int(bits[0:4]) - i2 = _binstr2int(bits[4:6]) - i3 = _binstr2int(bits[6:8]) - i4 = _binstr2int(bits[8:10]) - i5 = _binstr2int(bits[10:12]) - i6 = _binstr2int(bits[12:16]) - return '%08lx-%04lx-%04lx-%04lx-%04lx%08lx' % (i1,i2,i3,i4,i5,i6) - -def uuid_bits_to_uuid(bits): - return UUID(uuid_bits_to_string(bits)) - - -try: - from mulib import stacked - stacked.NoProducer() # just to exercise stacked -except: - #print "Couldn't import mulib.stacked, not registering UUID converter" - pass -else: - def convertUUID(uuid, req): - req.write(str(uuid)) - - stacked.add_producer(UUID, convertUUID, "*/*") - stacked.add_producer(UUID, convertUUID, "text/html") diff --git a/indra/lib/python/indra/base/metrics.py b/indra/lib/python/indra/base/metrics.py deleted file mode 100755 index ff8380265f..0000000000 --- a/indra/lib/python/indra/base/metrics.py +++ /dev/null @@ -1,121 +0,0 @@ -"""\ -@file metrics.py -@author Phoenix -@date 2007-11-27 -@brief simple interface for logging metrics - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys -try: - import syslog -except ImportError: - # Windows - import sys - class syslog(object): - # wrap to a lame syslog for windows - _logfp = sys.stderr - def syslog(msg): - _logfp.write(msg) - if not msg.endswith('\n'): - _logfp.write('\n') - syslog = staticmethod(syslog) - -from indra.base.llsd import format_notation - -def record_metrics(table, stats): - "Write a standard metrics log" - _log("LLMETRICS", table, stats) - -def record_event(table, data): - "Write a standard logmessage log" - _log("LLLOGMESSAGE", table, data) - -def set_destination(dest): - """Set the destination of metrics logs for this process. - - If you do not call this function prior to calling a logging - method, that function will open sys.stdout as a destination. - Attempts to set dest to None will throw a RuntimeError. - @param dest a file-like object which will be the destination for logs.""" - if dest is None: - raise RuntimeError("Attempt to unset metrics destination.") - global _destination - _destination = dest - -def destination(): - """Get the destination of the metrics logs for this process. - Returns None if no destination is set""" - global _destination - return _destination - -class SysLogger(object): - "A file-like object which writes to syslog." - def __init__(self, ident='indra', logopt = None, facility = None): - try: - if logopt is None: - logopt = syslog.LOG_CONS | syslog.LOG_PID - if facility is None: - facility = syslog.LOG_LOCAL0 - syslog.openlog(ident, logopt, facility) - import atexit - atexit.register(syslog.closelog) - except AttributeError: - # No syslog module on Windows - pass - - def write(str): - syslog.syslog(str) - write = staticmethod(write) - - def flush(): - pass - flush = staticmethod(flush) - -# -# internal API -# -_sequence_id = 0 -_destination = None - -def _next_id(): - global _sequence_id - next = _sequence_id - _sequence_id += 1 - return next - -def _dest(): - global _destination - if _destination is None: - # this default behavior is documented in the metrics functions above. - _destination = sys.stdout - return _destination - -def _log(header, table, data): - log_line = "%s (%d) %s %s" \ - % (header, _next_id(), table, format_notation(data)) - dest = _dest() - dest.write(log_line) - dest.flush() diff --git a/indra/lib/python/indra/ipc/__init__.py b/indra/lib/python/indra/ipc/__init__.py deleted file mode 100755 index 302bbf4a03..0000000000 --- a/indra/lib/python/indra/ipc/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -"""\ -@file __init__.py -@brief Initialization file for the indra ipc module. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" diff --git a/indra/lib/python/indra/ipc/compatibility.py b/indra/lib/python/indra/ipc/compatibility.py deleted file mode 100755 index b9045c22f3..0000000000 --- a/indra/lib/python/indra/ipc/compatibility.py +++ /dev/null @@ -1,123 +0,0 @@ -"""\ -@file compatibility.py -@brief Classes that manage compatibility states. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - - -"""Compatibility combination table: - - I M O N S - -- -- -- -- -- -I: I I I I I -M: I M M M M -O: I M O M O -N: I M M N N -S: I M O N S - -""" - -class _Compatibility(object): - def __init__(self, reason): - self.reasons = [ ] - if reason: - self.reasons.append(reason) - - def combine(self, other): - if self._level() <= other._level(): - return self._buildclone(other) - else: - return other._buildclone(self) - - def prefix(self, leadin): - self.reasons = [ leadin + r for r in self.reasons ] - - def same(self): return self._level() >= 1 - def deployable(self): return self._level() > 0 - def resolved(self): return self._level() > -1 - def compatible(self): return self._level() > -2 - - def explain(self): - return self.__class__.__name__ + "\n" + "\n".join(self.reasons) + "\n" - - def _buildclone(self, other=None): - c = self._buildinstance() - c.reasons = self.reasons - if other: - c.reasons = c.reasons + other.reasons - return c - - def _buildinstance(self): - return self.__class__(None) - -# def _level(self): -# raise RuntimeError('implement in subclass') - - -class Incompatible(_Compatibility): - def _level(self): - return -2 - -class Mixed(_Compatibility): - def __init__(self, *inputs): - _Compatibility.__init__(self, None) - for i in inputs: - self.reasons += i.reasons - - def _buildinstance(self): - return self.__class__() - - def _level(self): - return -1 - -class _Aged(_Compatibility): - def combine(self, other): - if self._level() == other._level(): - return self._buildclone(other) - if int(self._level()) == int(other._level()): - return Mixed(self, other) - return _Compatibility.combine(self, other) - -class Older(_Aged): - def _level(self): - return -0.25 - -class Newer(_Aged): - def _level(self): - return 0.25 - -class Same(_Compatibility): - def __init__(self): - _Compatibility.__init__(self, None) - - def _buildinstance(self): - return self.__class__() - - def _level(self): - return 1 - - - - diff --git a/indra/lib/python/indra/ipc/httputil.py b/indra/lib/python/indra/ipc/httputil.py deleted file mode 100755 index d53f34a771..0000000000 --- a/indra/lib/python/indra/ipc/httputil.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/python -## $LicenseInfo:firstyear=2011&license=viewerlgpl$ -## Second Life Viewer Source Code -## Copyright (C) 2011, 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$ - -import warnings - -warnings.warn("indra.ipc.httputil has been deprecated; use eventlet.httpc instead", DeprecationWarning, 2) - -from eventlet.httpc import * - - -makeConnection = make_connection diff --git a/indra/lib/python/indra/ipc/llmessage.py b/indra/lib/python/indra/ipc/llmessage.py deleted file mode 100755 index 91fb36b72c..0000000000 --- a/indra/lib/python/indra/ipc/llmessage.py +++ /dev/null @@ -1,372 +0,0 @@ -"""\ -@file llmessage.py -@brief Message template parsing and compatiblity - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from compatibility import Incompatible, Older, Newer, Same -from tokenstream import TokenStream - -### -### Message Template -### - -class Template: - def __init__(self): - self.messages = { } - - def addMessage(self, m): - self.messages[m.name] = m - - def compatibleWithBase(self, base): - messagenames = ( - frozenset(self.messages.keys()) - | frozenset(base.messages.keys()) - ) - - compatibility = Same() - for name in messagenames: - selfmessage = self.messages.get(name, None) - basemessage = base.messages.get(name, None) - - if not selfmessage: - c = Older("missing message %s, did you mean to deprecate?" % name) - elif not basemessage: - c = Newer("added message %s" % name) - else: - c = selfmessage.compatibleWithBase(basemessage) - c.prefix("in message %s: " % name) - - compatibility = compatibility.combine(c) - - return compatibility - - - -class Message: - HIGH = "High" - MEDIUM = "Medium" - LOW = "Low" - FIXED = "Fixed" - priorities = [ HIGH, MEDIUM, LOW, FIXED ] - prioritieswithnumber = [ FIXED ] - - TRUSTED = "Trusted" - NOTTRUSTED = "NotTrusted" - trusts = [ TRUSTED, NOTTRUSTED ] - - UNENCODED = "Unencoded" - ZEROCODED = "Zerocoded" - encodings = [ UNENCODED, ZEROCODED ] - - NOTDEPRECATED = "NotDeprecated" - DEPRECATED = "Deprecated" - UDPDEPRECATED = "UDPDeprecated" - UDPBLACKLISTED = "UDPBlackListed" - deprecations = [ NOTDEPRECATED, UDPDEPRECATED, UDPBLACKLISTED, DEPRECATED ] - # in order of increasing deprecation - - def __init__(self, name, number, priority, trust, coding): - self.name = name - self.number = number - self.priority = priority - self.trust = trust - self.coding = coding - self.deprecateLevel = 0 - self.blocks = [ ] - - def deprecated(self): - return self.deprecateLevel != 0 - - def deprecate(self, deprecation): - self.deprecateLevel = self.deprecations.index(deprecation) - - def addBlock(self, block): - self.blocks.append(block) - - def compatibleWithBase(self, base): - if self.name != base.name: - # this should never happen in real life because of the - # way Template matches up messages by name - return Incompatible("has different name: %s vs. %s in base" - % (self.name, base.name)) - if self.priority != base.priority: - return Incompatible("has different priority: %s vs. %s in base" - % (self.priority, base.priority)) - if self.trust != base.trust: - return Incompatible("has different trust: %s vs. %s in base" - % (self.trust, base.trust)) - if self.coding != base.coding: - return Incompatible("has different coding: %s vs. %s in base" - % (self.coding, base.coding)) - if self.number != base.number: - return Incompatible("has different number: %s vs. %s in base" - % (self.number, base.number)) - - compatibility = Same() - - if self.deprecateLevel != base.deprecateLevel: - if self.deprecateLevel < base.deprecateLevel: - c = Older("is less deprecated: %s vs. %s in base" % ( - self.deprecations[self.deprecateLevel], - self.deprecations[base.deprecateLevel])) - else: - c = Newer("is more deprecated: %s vs. %s in base" % ( - self.deprecations[self.deprecateLevel], - self.deprecations[base.deprecateLevel])) - compatibility = compatibility.combine(c) - - selflen = len(self.blocks) - baselen = len(base.blocks) - samelen = min(selflen, baselen) - - for i in xrange(0, samelen): - selfblock = self.blocks[i] - baseblock = base.blocks[i] - - c = selfblock.compatibleWithBase(baseblock) - if not c.same(): - c = Incompatible("block %d isn't identical" % i) - compatibility = compatibility.combine(c) - - if selflen > baselen: - c = Newer("has %d extra blocks" % (selflen - baselen)) - elif selflen < baselen: - c = Older("missing %d extra blocks" % (baselen - selflen)) - else: - c = Same() - - compatibility = compatibility.combine(c) - return compatibility - - - -class Block(object): - SINGLE = "Single" - MULTIPLE = "Multiple" - VARIABLE = "Variable" - repeats = [ SINGLE, MULTIPLE, VARIABLE ] - repeatswithcount = [ MULTIPLE ] - - def __init__(self, name, repeat, count=None): - self.name = name - self.repeat = repeat - self.count = count - self.variables = [ ] - - def addVariable(self, variable): - self.variables.append(variable) - - def compatibleWithBase(self, base): - if self.name != base.name: - return Incompatible("has different name: %s vs. %s in base" - % (self.name, base.name)) - if self.repeat != base.repeat: - return Incompatible("has different repeat: %s vs. %s in base" - % (self.repeat, base.repeat)) - if self.repeat in Block.repeatswithcount: - if self.count != base.count: - return Incompatible("has different count: %s vs. %s in base" - % (self.count, base.count)) - - compatibility = Same() - - selflen = len(self.variables) - baselen = len(base.variables) - - for i in xrange(0, min(selflen, baselen)): - selfvar = self.variables[i] - basevar = base.variables[i] - - c = selfvar.compatibleWithBase(basevar) - if not c.same(): - c = Incompatible("variable %d isn't identical" % i) - compatibility = compatibility.combine(c) - - if selflen > baselen: - c = Newer("has %d extra variables" % (selflen - baselen)) - elif selflen < baselen: - c = Older("missing %d extra variables" % (baselen - selflen)) - else: - c = Same() - - compatibility = compatibility.combine(c) - return compatibility - - - -class Variable: - U8 = "U8"; U16 = "U16"; U32 = "U32"; U64 = "U64" - S8 = "S8"; S16 = "S16"; S32 = "S32"; S64 = "S64" - F32 = "F32"; F64 = "F64" - LLVECTOR3 = "LLVector3"; LLVECTOR3D = "LLVector3d"; LLVECTOR4 = "LLVector4" - LLQUATERNION = "LLQuaternion" - LLUUID = "LLUUID" - BOOL = "BOOL" - IPADDR = "IPADDR"; IPPORT = "IPPORT" - FIXED = "Fixed" - VARIABLE = "Variable" - types = [ U8, U16, U32, U64, S8, S16, S32, S64, F32, F64, - LLVECTOR3, LLVECTOR3D, LLVECTOR4, LLQUATERNION, - LLUUID, BOOL, IPADDR, IPPORT, FIXED, VARIABLE ] - typeswithsize = [ FIXED, VARIABLE ] - - def __init__(self, name, type, size): - self.name = name - self.type = type - self.size = size - - def compatibleWithBase(self, base): - if self.name != base.name: - return Incompatible("has different name: %s vs. %s in base" - % (self.name, base.name)) - if self.type != base.type: - return Incompatible("has different type: %s vs. %s in base" - % (self.type, base.type)) - if self.type in Variable.typeswithsize: - if self.size != base.size: - return Incompatible("has different size: %s vs. %s in base" - % (self.size, base.size)) - return Same() - - - -### -### Parsing Message Templates -### - -class TemplateParser: - def __init__(self, tokens): - self._tokens = tokens - self._version = 0 - self._numbers = { } - for p in Message.priorities: - self._numbers[p] = 0 - - def parseTemplate(self): - tokens = self._tokens - t = Template() - while True: - if tokens.want("version"): - v = float(tokens.require(tokens.wantFloat())) - self._version = v - t.version = v - continue - - m = self.parseMessage() - if m: - t.addMessage(m) - continue - - if self._version >= 2.0: - tokens.require(tokens.wantEOF()) - break - else: - if tokens.wantEOF(): - break - - tokens.consume() - # just assume (gulp) that this is a comment - # line 468: "sim -> dataserver" - return t - - - def parseMessage(self): - tokens = self._tokens - if not tokens.want("{"): - return None - - name = tokens.require(tokens.wantSymbol()) - priority = tokens.require(tokens.wantOneOf(Message.priorities)) - - if self._version >= 2.0 or priority in Message.prioritieswithnumber: - number = int("+" + tokens.require(tokens.wantInteger()), 0) - else: - self._numbers[priority] += 1 - number = self._numbers[priority] - - trust = tokens.require(tokens.wantOneOf(Message.trusts)) - coding = tokens.require(tokens.wantOneOf(Message.encodings)) - - m = Message(name, number, priority, trust, coding) - - if self._version >= 2.0: - d = tokens.wantOneOf(Message.deprecations) - if d: - m.deprecate(d) - - while True: - b = self.parseBlock() - if not b: - break - m.addBlock(b) - - tokens.require(tokens.want("}")) - - return m - - - def parseBlock(self): - tokens = self._tokens - if not tokens.want("{"): - return None - name = tokens.require(tokens.wantSymbol()) - repeat = tokens.require(tokens.wantOneOf(Block.repeats)) - if repeat in Block.repeatswithcount: - count = int(tokens.require(tokens.wantInteger())) - else: - count = None - - b = Block(name, repeat, count) - - while True: - v = self.parseVariable() - if not v: - break - b.addVariable(v) - - tokens.require(tokens.want("}")) - return b - - - def parseVariable(self): - tokens = self._tokens - if not tokens.want("{"): - return None - name = tokens.require(tokens.wantSymbol()) - type = tokens.require(tokens.wantOneOf(Variable.types)) - if type in Variable.typeswithsize: - size = tokens.require(tokens.wantInteger()) - else: - tokens.wantInteger() # in LandStatRequest: "{ ParcelLocalID S32 1 }" - size = None - tokens.require(tokens.want("}")) - return Variable(name, type, size) - -def parseTemplateString(s): - return TemplateParser(TokenStream().fromString(s)).parseTemplate() - -def parseTemplateFile(f): - return TemplateParser(TokenStream().fromFile(f)).parseTemplate() diff --git a/indra/lib/python/indra/ipc/llsdhttp.py b/indra/lib/python/indra/ipc/llsdhttp.py deleted file mode 100755 index cbe8ee1eca..0000000000 --- a/indra/lib/python/indra/ipc/llsdhttp.py +++ /dev/null @@ -1,100 +0,0 @@ -"""\ -@file llsdhttp.py -@brief Functions to ease moving llsd over http - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import os.path -import os -import urlparse - -from indra.base import llsd - -from eventlet import httpc - -suite = httpc.HttpSuite(llsd.format_xml, llsd.parse, 'application/llsd+xml') -delete = suite.delete -delete_ = suite.delete_ -get = suite.get -get_ = suite.get_ -head = suite.head -head_ = suite.head_ -post = suite.post -post_ = suite.post_ -put = suite.put -put_ = suite.put_ -request = suite.request -request_ = suite.request_ - -# import every httpc error exception into our namespace for convenience -for x in httpc.status_to_error_map.itervalues(): - globals()[x.__name__] = x -ConnectionError = httpc.ConnectionError -Retriable = httpc.Retriable - -for x in (httpc.ConnectionError,): - globals()[x.__name__] = x - - -def postFile(url, filename): - f = open(filename) - body = f.read() - f.close() - llsd_body = llsd.parse(body) - return post_(url, llsd_body) - - -# deprecated in favor of get_ -def getStatus(url, use_proxy=False): - status, _headers, _body = get_(url, use_proxy=use_proxy) - return status - -# deprecated in favor of put_ -def putStatus(url, data): - status, _headers, _body = put_(url, data) - return status - -# deprecated in favor of delete_ -def deleteStatus(url): - status, _headers, _body = delete_(url) - return status - -# deprecated in favor of post_ -def postStatus(url, data): - status, _headers, _body = post_(url, data) - return status - - -def postFileStatus(url, filename): - status, _headers, body = postFile(url, filename) - return status, body - - -def getFromSimulator(path, use_proxy=False): - return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy) - - -def postToSimulator(path, data=None): - return post('http://' + simulatorHostAndPort + path, data) diff --git a/indra/lib/python/indra/ipc/mysql_pool.py b/indra/lib/python/indra/ipc/mysql_pool.py deleted file mode 100755 index e5855a3091..0000000000 --- a/indra/lib/python/indra/ipc/mysql_pool.py +++ /dev/null @@ -1,81 +0,0 @@ -"""\ -@file mysql_pool.py -@brief Thin wrapper around eventlet.db_pool that chooses MySQLdb and Tpool. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import MySQLdb -from eventlet import db_pool - -class DatabaseConnector(db_pool.DatabaseConnector): - def __init__(self, credentials, *args, **kwargs): - super(DatabaseConnector, self).__init__(MySQLdb, credentials, - conn_pool=db_pool.ConnectionPool, - *args, **kwargs) - - # get is extended relative to eventlet.db_pool to accept a port argument - def get(self, host, dbname, port=3306): - key = (host, dbname, port) - if key not in self._databases: - new_kwargs = self._kwargs.copy() - new_kwargs['db'] = dbname - new_kwargs['host'] = host - new_kwargs['port'] = port - new_kwargs.update(self.credentials_for(host)) - dbpool = ConnectionPool(*self._args, **new_kwargs) - self._databases[key] = dbpool - - return self._databases[key] - -class ConnectionPool(db_pool.TpooledConnectionPool): - """A pool which gives out saranwrapped MySQLdb connections from a pool - """ - - def __init__(self, *args, **kwargs): - super(ConnectionPool, self).__init__(MySQLdb, *args, **kwargs) - - def get(self): - conn = super(ConnectionPool, self).get() - # annotate the connection object with the details on the - # connection; this is used elsewhere to check that you haven't - # suddenly changed databases in midstream while making a - # series of queries on a connection. - arg_names = ['host','user','passwd','db','port','unix_socket','conv','connect_timeout', - 'compress', 'named_pipe', 'init_command', 'read_default_file', 'read_default_group', - 'cursorclass', 'use_unicode', 'charset', 'sql_mode', 'client_flag', 'ssl', - 'local_infile'] - # you could have constructed this connectionpool with a mix of - # keyword and non-keyword arguments, but we want to annotate - # the connection object with a dict so it's easy to check - # against so here we are converting the list of non-keyword - # arguments (in self._args) into a dict of keyword arguments, - # and merging that with the actual keyword arguments - # (self._kwargs). The arg_names variable lists the - # constructor arguments for MySQLdb Connection objects. - converted_kwargs = dict([ (arg_names[i], arg) for i, arg in enumerate(self._args) ]) - converted_kwargs.update(self._kwargs) - conn.connection_parameters = converted_kwargs - return conn - diff --git a/indra/lib/python/indra/ipc/russ.py b/indra/lib/python/indra/ipc/russ.py deleted file mode 100755 index ac780f128b..0000000000 --- a/indra/lib/python/indra/ipc/russ.py +++ /dev/null @@ -1,165 +0,0 @@ -"""\ -@file russ.py -@brief Recursive URL Substitution Syntax helpers -@author Phoenix - -Many details on how this should work is available on the wiki: -https://wiki.secondlife.com/wiki/Recursive_URL_Substitution_Syntax - -Adding features to this should be reflected in that page in the -implementations section. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import urllib -from indra.ipc import llsdhttp - -class UnbalancedBraces(Exception): - pass - -class UnknownDirective(Exception): - pass - -class BadDirective(Exception): - pass - -def format_value_for_path(value): - if type(value) in [list, tuple]: - # *NOTE: treat lists as unquoted path components so that the quoting - # doesn't get out-of-hand. This is a workaround for the fact that - # russ always quotes, even if the data it's given is already quoted, - # and it's not safe to simply unquote a path directly, so if we want - # russ to substitute urls parts inside other url parts we always - # have to do so via lists of unquoted path components. - return '/'.join([urllib.quote(str(item)) for item in value]) - else: - return urllib.quote(str(value)) - -def format(format_str, context): - """@brief Format format string according to rules for RUSS. -@see https://osiris.lindenlab.com/mediawiki/index.php/Recursive_URL_Substitution_Syntax -@param format_str The input string to format. -@param context A map used for string substitutions. -@return Returns the formatted string. If no match, the braces remain intact. -""" - while True: - #print "format_str:", format_str - all_matches = _find_sub_matches(format_str) - if not all_matches: - break - substitutions = 0 - while True: - matches = all_matches.pop() - # we work from right to left to make sure we do not - # invalidate positions earlier in format_str - matches.reverse() - for pos in matches: - # Use index since _find_sub_matches should have raised - # an exception, and failure to find now is an exception. - end = format_str.index('}', pos) - #print "directive:", format_str[pos+1:pos+5] - if format_str[pos + 1] == '$': - value = context[format_str[pos + 2:end]] - if value is not None: - value = format_value_for_path(value) - elif format_str[pos + 1] == '%': - value = _build_query_string( - context.get(format_str[pos + 2:end])) - elif format_str[pos+1:pos+5] == 'http' or format_str[pos+1:pos+5] == 'file': - value = _fetch_url_directive(format_str[pos + 1:end]) - else: - raise UnknownDirective, format_str[pos:end + 1] - if value is not None: - format_str = format_str[:pos]+str(value)+format_str[end+1:] - substitutions += 1 - - # If there were any substitutions at this depth, re-parse - # since this may have revealed new things to substitute - if substitutions: - break - if not all_matches: - break - - # If there were no substitutions at all, and we have exhausted - # the possible matches, bail. - if not substitutions: - break - return format_str - -def _find_sub_matches(format_str): - """@brief Find all of the substitution matches. -@param format_str the RUSS conformant format string. -@return Returns an array of depths of arrays of positional matches in input. -""" - depth = 0 - matches = [] - for pos in range(len(format_str)): - if format_str[pos] == '{': - depth += 1 - if not len(matches) == depth: - matches.append([]) - matches[depth - 1].append(pos) - continue - if format_str[pos] == '}': - depth -= 1 - continue - if not depth == 0: - raise UnbalancedBraces, format_str - return matches - -def _build_query_string(query_dict): - """\ - @breif given a dict, return a query string. utility wrapper for urllib. - @param query_dict input query dict - @returns Returns an urlencoded query string including leading '?'. - """ - if query_dict: - keys = query_dict.keys() - keys.sort() - def stringize(value): - if type(value) in (str,unicode): - return value - else: - return str(value) - query_list = [urllib.quote(str(key)) + '=' + urllib.quote(stringize(query_dict[key])) for key in keys] - return '?' + '&'.join(query_list) - else: - return '' - -def _fetch_url_directive(directive): - "*FIX: This only supports GET" - commands = directive.split('|') - resource = llsdhttp.get(commands[0]) - if len(commands) == 3: - resource = _walk_resource(resource, commands[2]) - return resource - -def _walk_resource(resource, path): - path = path.split('/') - for child in path: - if not child: - continue - resource = resource[child] - return resource diff --git a/indra/lib/python/indra/ipc/servicebuilder.py b/indra/lib/python/indra/ipc/servicebuilder.py deleted file mode 100755 index 0a0ce2b4e2..0000000000 --- a/indra/lib/python/indra/ipc/servicebuilder.py +++ /dev/null @@ -1,134 +0,0 @@ -"""\ -@file servicebuilder.py -@author Phoenix -@brief Class which will generate service urls. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from indra.base import config -from indra.ipc import llsdhttp -from indra.ipc import russ - -# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack -services_config = {} -try: - services_config = llsdhttp.get(config.get('services-config')) -except: - pass - -_g_builder = None -def _builder(): - global _g_builder - if _g_builder is None: - _g_builder = ServiceBuilder() - return _g_builder - -def build(name, context={}, **kwargs): - """ Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both! - - Example use: - > context = {'channel':'Second Life Release', 'version':'1.18.2.0'} - > servicebuilder.build('version-manager-version', context) - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0' - > servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0') - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0' - > servicebuilder.build('version-manager-version', context, version='1.18.1.2') - 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' - """ - global _g_builder - if _g_builder is None: - _g_builder = ServiceBuilder() - return _g_builder.buildServiceURL(name, context, **kwargs) - -def build_path(name, context={}, **kwargs): - context = context.copy() # shouldn't modify the caller's dictionary - context.update(kwargs) - return _builder().buildPath(name, context) - -class ServiceBuilder(object): - def __init__(self, services_definition = services_config): - """\ - @brief - @brief Create a ServiceBuilder. - @param services_definition Complete services definition, services.xml. - """ - # no need to keep a copy of the services section of the - # complete services definition, but it doesn't hurt much. - self.services = services_definition['services'] - self.builders = {} - for service in self.services: - service_builder = service.get('service-builder') - if not service_builder: - continue - if isinstance(service_builder, dict): - # We will be constructing several builders - for name, builder in service_builder.iteritems(): - full_builder_name = service['name'] + '-' + name - self.builders[full_builder_name] = builder - else: - self.builders[service['name']] = service_builder - - def buildPath(self, name, context): - """\ - @brief given the environment on construction, return a service path. - @param name The name of the service. - @param context A dict of name value lookups for the service. - @returns Returns the - """ - return russ.format(self.builders[name], context) - - def buildServiceURL(self, name, context={}, **kwargs): - """\ - @brief given the environment on construction, return a service URL. - @param name The name of the service. - @param context A dict of name value lookups for the service. - @param kwargs Any keyword arguments are treated as members of the - context, this allows you to be all 31337 by writing shit like: - servicebuilder.build('name', param=value) - @returns Returns the - """ - context = context.copy() # shouldn't modify the caller's dictionary - context.update(kwargs) - base_url = config.get('services-base-url') - svc_path = russ.format(self.builders[name], context) - return base_url + svc_path - - -def on_in(query_name, host_key, schema_key): - """\ - @brief Constructs an on/in snippet (for running named queries) - from a schema name and two keys referencing values stored in - indra.xml. - - @param query_name Name of the query. - @param host_key Logical name of destination host. Will be - looked up in indra.xml. - @param schema_key Logical name of destination schema. Will - be looked up in indra.xml. - """ - return "on/config:%s/in/config:%s/%s" % (host_key.strip('/'), - schema_key.strip('/'), - query_name.lstrip('/')) - diff --git a/indra/lib/python/indra/ipc/siesta.py b/indra/lib/python/indra/ipc/siesta.py deleted file mode 100755 index d867e71537..0000000000 --- a/indra/lib/python/indra/ipc/siesta.py +++ /dev/null @@ -1,468 +0,0 @@ -"""\ -@file siesta.py -@brief A tiny llsd based RESTful web services framework - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from indra.base import config -from indra.base import llsd -from webob import exc -import webob -import re, socket - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - -try: - import cjson - json_decode = cjson.decode - json_encode = cjson.encode - JsonDecodeError = cjson.DecodeError - JsonEncodeError = cjson.EncodeError -except ImportError: - import simplejson - json_decode = simplejson.loads - json_encode = simplejson.dumps - JsonDecodeError = ValueError - JsonEncodeError = TypeError - - -llsd_parsers = { - 'application/json': json_decode, - llsd.BINARY_MIME_TYPE: llsd.parse_binary, - 'application/llsd+notation': llsd.parse_notation, - llsd.XML_MIME_TYPE: llsd.parse_xml, - 'application/xml': llsd.parse_xml, - } - - -def mime_type(content_type): - '''Given a Content-Type header, return only the MIME type.''' - - return content_type.split(';', 1)[0].strip().lower() - -class BodyLLSD(object): - '''Give a webob Request or Response an llsd based "content" property. - - Getting the content property parses the body, and caches the result. - - Setting the content property formats a payload, and the body property - is set.''' - - def _llsd__get(self): - '''Get, set, or delete the LLSD value stored in this object.''' - - try: - return self._llsd - except AttributeError: - if not self.body: - raise AttributeError('No llsd attribute has been set') - else: - mtype = mime_type(self.content_type) - try: - parser = llsd_parsers[mtype] - except KeyError: - raise exc.HTTPUnsupportedMediaType( - 'Content type %s not supported' % mtype).exception - try: - self._llsd = parser(self.body) - except (llsd.LLSDParseError, JsonDecodeError, TypeError), err: - raise exc.HTTPBadRequest( - 'Could not parse body: %r' % err.args).exception - return self._llsd - - def _llsd__set(self, val): - req = getattr(self, 'request', None) - if req is not None: - formatter, ctype = formatter_for_request(req) - self.content_type = ctype - else: - formatter, ctype = formatter_for_mime_type( - mime_type(self.content_type)) - self.body = formatter(val) - - def _llsd__del(self): - if hasattr(self, '_llsd'): - del self._llsd - - content = property(_llsd__get, _llsd__set, _llsd__del) - - -class Response(webob.Response, BodyLLSD): - '''Response class with LLSD support. - - A sensible default content type is used. - - Setting the llsd property also sets the body. Getting the llsd - property parses the body if necessary. - - If you set the body property directly, the llsd property will be - deleted.''' - - default_content_type = 'application/llsd+xml' - - def _body__set(self, body): - if hasattr(self, '_llsd'): - del self._llsd - super(Response, self)._body__set(body) - - def cache_forever(self): - self.cache_expires(86400 * 365) - - body = property(webob.Response._body__get, _body__set, - webob.Response._body__del, - webob.Response._body__get.__doc__) - - -class Request(webob.Request, BodyLLSD): - '''Request class with LLSD support. - - Sensible content type and accept headers are used by default. - - Setting the content property also sets the body. Getting the content - property parses the body if necessary. - - If you set the body property directly, the content property will be - deleted.''' - - default_content_type = 'application/llsd+xml' - default_accept = ('application/llsd+xml; q=0.5, ' - 'application/llsd+notation; q=0.3, ' - 'application/llsd+binary; q=0.2, ' - 'application/xml; q=0.1, ' - 'application/json; q=0.0') - - def __init__(self, environ=None, *args, **kwargs): - if environ is None: - environ = {} - else: - environ = environ.copy() - if 'CONTENT_TYPE' not in environ: - environ['CONTENT_TYPE'] = self.default_content_type - if 'HTTP_ACCEPT' not in environ: - environ['HTTP_ACCEPT'] = self.default_accept - super(Request, self).__init__(environ, *args, **kwargs) - - def _body__set(self, body): - if hasattr(self, '_llsd'): - del self._llsd - super(Request, self)._body__set(body) - - def path_urljoin(self, *parts): - return '/'.join([path_url.rstrip('/')] + list(parts)) - - body = property(webob.Request._body__get, _body__set, - webob.Request._body__del, webob.Request._body__get.__doc__) - - def create_response(self, content=None, status='200 OK', - conditional_response=webob.NoDefault): - resp = self.ResponseClass(status=status, request=self, - conditional_response=conditional_response) - resp.content = content - return resp - - def curl(self): - '''Create and fill out a pycurl easy object from this request.''' - - import pycurl - c = pycurl.Curl() - c.setopt(pycurl.URL, self.url()) - if self.headers: - c.setopt(pycurl.HTTPHEADER, - ['%s: %s' % (k, self.headers[k]) for k in self.headers]) - c.setopt(pycurl.FOLLOWLOCATION, True) - c.setopt(pycurl.AUTOREFERER, True) - c.setopt(pycurl.MAXREDIRS, 16) - c.setopt(pycurl.NOSIGNAL, True) - c.setopt(pycurl.READFUNCTION, self.body_file.read) - c.setopt(pycurl.SSL_VERIFYHOST, 2) - - if self.method == 'POST': - c.setopt(pycurl.POST, True) - post301 = getattr(pycurl, 'POST301', None) - if post301 is not None: - # Added in libcurl 7.17.1. - c.setopt(post301, True) - elif self.method == 'PUT': - c.setopt(pycurl.PUT, True) - elif self.method != 'GET': - c.setopt(pycurl.CUSTOMREQUEST, self.method) - return c - -Request.ResponseClass = Response -Response.RequestClass = Request - - -llsd_formatters = { - 'application/json': json_encode, - 'application/llsd+binary': llsd.format_binary, - 'application/llsd+notation': llsd.format_notation, - 'application/llsd+xml': llsd.format_xml, - 'application/xml': llsd.format_xml, - } - -formatter_qualities = ( - ('application/llsd+xml', 1.0), - ('application/llsd+notation', 0.5), - ('application/llsd+binary', 0.4), - ('application/xml', 0.3), - ('application/json', 0.2), - ) - -def formatter_for_mime_type(mime_type): - '''Return a formatter that encodes to the given MIME type. - - The result is a pair of function and MIME type.''' - try: - return llsd_formatters[mime_type], mime_type - except KeyError: - raise exc.HTTPInternalServerError( - 'Could not use MIME type %r to format response' % - mime_type).exception - - -def formatter_for_request(req): - '''Return a formatter that encodes to the preferred type of the client. - - The result is a pair of function and actual MIME type.''' - ctype = req.accept.best_match(formatter_qualities) - try: - return llsd_formatters[ctype], ctype - except KeyError: - raise exc.HTTPNotAcceptable().exception - - -def wsgi_adapter(func, environ, start_response): - '''Adapt a Siesta callable to act as a WSGI application.''' - # Process the request as appropriate. - try: - req = Request(environ) - #print req.urlvars - resp = func(req, **req.urlvars) - if not isinstance(resp, webob.Response): - try: - formatter, ctype = formatter_for_request(req) - resp = req.ResponseClass(formatter(resp), content_type=ctype) - resp._llsd = resp - except (JsonEncodeError, TypeError), err: - resp = exc.HTTPInternalServerError( - detail='Could not format response') - except exc.HTTPException, e: - resp = e - except socket.error, e: - resp = exc.HTTPInternalServerError(detail=e.args[1]) - return resp(environ, start_response) - - -def llsd_callable(func): - '''Turn a callable into a Siesta application.''' - - def replacement(environ, start_response): - return wsgi_adapter(func, environ, start_response) - - return replacement - - -def llsd_method(http_method, func): - def replacement(environ, start_response): - if environ['REQUEST_METHOD'] == http_method: - return wsgi_adapter(func, environ, start_response) - return exc.HTTPMethodNotAllowed()(environ, start_response) - - return replacement - - -http11_methods = 'OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT'.split() -http11_methods.sort() - -def llsd_class(cls): - '''Turn a class into a Siesta application. - - A new instance is created for each request. A HTTP method FOO is - turned into a call to the handle_foo method of the instance.''' - - def foo(req, **kwargs): - instance = cls() - method = req.method.lower() - try: - handler = getattr(instance, 'handle_' + method) - except AttributeError: - allowed = [m for m in http11_methods - if hasattr(instance, 'handle_' + m.lower())] - raise exc.HTTPMethodNotAllowed( - headers={'Allow': ', '.join(allowed)}).exception - #print "kwargs: ", kwargs - return handler(req, **kwargs) - - def replacement(environ, start_response): - return wsgi_adapter(foo, environ, start_response) - - return replacement - - -def curl(reqs): - import pycurl - - m = pycurl.CurlMulti() - curls = [r.curl() for r in reqs] - io = {} - for c in curls: - fp = StringIO() - hdr = StringIO() - c.setopt(pycurl.WRITEFUNCTION, fp.write) - c.setopt(pycurl.HEADERFUNCTION, hdr.write) - io[id(c)] = fp, hdr - m.handles = curls - try: - while True: - ret, num_handles = m.perform() - if ret != pycurl.E_CALL_MULTI_PERFORM: - break - finally: - m.close() - - for req, c in zip(reqs, curls): - fp, hdr = io[id(c)] - hdr.seek(0) - status = hdr.readline().rstrip() - headers = [] - name, values = None, None - - # XXX We don't currently handle bogus header data. - - for line in hdr.readlines(): - if not line[0].isspace(): - if name: - headers.append((name, ' '.join(values))) - name, value = line.strip().split(':', 1) - value = [value] - else: - values.append(line.strip()) - if name: - headers.append((name, ' '.join(values))) - - resp = c.ResponseClass(fp.getvalue(), status, headers, request=req) - - -route_re = re.compile(r''' - \{ # exact character "{" - (\w*) # "config" or variable (restricted to a-z, 0-9, _) - (?:([:~])([^}]+))? # optional :type or ~regex part - \} # exact character "}" - ''', re.VERBOSE) - -predefined_regexps = { - 'uuid': r'[a-f0-9][a-f0-9-]{31,35}', - 'int': r'\d+', - 'host': r'[a-z0-9][a-z0-9\-\.]*', - } - -def compile_route(route): - fp = StringIO() - last_pos = 0 - for match in route_re.finditer(route): - #print "matches: ", match.groups() - fp.write(re.escape(route[last_pos:match.start()])) - var_name = match.group(1) - sep = match.group(2) - expr = match.group(3) - if var_name == 'config': - expr = re.escape(str(config.get(var_name))) - else: - if expr: - if sep == ':': - expr = predefined_regexps[expr] - # otherwise, treat what follows '~' as a regexp - else: - expr = '[^/]+' - if var_name != '': - expr = '(?P<%s>%s)' % (var_name, expr) - else: - expr = '(%s)' % (expr,) - fp.write(expr) - last_pos = match.end() - fp.write(re.escape(route[last_pos:])) - compiled_route = '^%s$' % fp.getvalue() - #print route, "->", compiled_route - return compiled_route - -class Router(object): - '''WSGI routing class. Parses a URL and hands off a request to - some other WSGI application. If no suitable application is found, - responds with a 404.''' - - def __init__(self): - self._new_routes = [] - self._routes = [] - self._paths = [] - - def add(self, route, app, methods=None): - self._new_routes.append((route, app, methods)) - - def _create_routes(self): - for route, app, methods in self._new_routes: - self._paths.append(route) - self._routes.append( - (re.compile(compile_route(route)), - app, - methods and dict.fromkeys(methods))) - self._new_routes = [] - - def __call__(self, environ, start_response): - # load up the config from the config file. Only needs to be - # done once per interpreter. This is the entry point of all - # siesta applications, so this is where we trap it. - _conf = config.get_config() - if _conf is None: - import os.path - fname = os.path.join( - environ.get('ll.config_dir', '/local/linden/etc'), - 'indra.xml') - config.load(fname) - - # proceed with handling the request - self._create_routes() - path_info = environ['PATH_INFO'] - request_method = environ['REQUEST_METHOD'] - allowed = [] - for regex, app, methods in self._routes: - m = regex.match(path_info) - if m: - #print "groupdict:",m.groupdict() - if not methods or request_method in methods: - environ['paste.urlvars'] = m.groupdict() - return app(environ, start_response) - else: - allowed += methods - if allowed: - allowed = dict.fromkeys(allows).keys() - allowed.sort() - resp = exc.HTTPMethodNotAllowed( - headers={'Allow': ', '.join(allowed)}) - else: - resp = exc.HTTPNotFound() - return resp(environ, start_response) diff --git a/indra/lib/python/indra/ipc/siesta_test.py b/indra/lib/python/indra/ipc/siesta_test.py deleted file mode 100755 index a35eed2460..0000000000 --- a/indra/lib/python/indra/ipc/siesta_test.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/python -## $LicenseInfo:firstyear=2011&license=viewerlgpl$ -## Second Life Viewer Source Code -## Copyright (C) 2011, 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$ -from indra.base import llsd, lluuid -from indra.ipc import siesta -import datetime, math, unittest -from webob import exc - - -class ClassApp(object): - def handle_get(self, req): - pass - - def handle_post(self, req): - return req.llsd - - -def callable_app(req): - if req.method == 'UNDERPANTS': - raise exc.HTTPMethodNotAllowed() - elif req.method == 'GET': - return None - return req.llsd - - -class TestBase: - def test_basic_get(self): - req = siesta.Request.blank('/') - self.assertEquals(req.get_response(self.server).body, - llsd.format_xml(None)) - - def test_bad_method(self): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'UNDERPANTS' - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPMethodNotAllowed.code) - - json_safe = { - 'none': None, - 'bool_true': True, - 'bool_false': False, - 'int_zero': 0, - 'int_max': 2147483647, - 'int_min': -2147483648, - 'long_zero': 0, - 'long_max': 2147483647L, - 'long_min': -2147483648L, - 'float_zero': 0, - 'float': math.pi, - 'float_huge': 3.14159265358979323846e299, - 'str_empty': '', - 'str': 'foo', - u'unic\u1e51de_empty': u'', - u'unic\u1e51de': u'\u1e4exx\u10480', - } - json_safe['array'] = json_safe.values() - json_safe['tuple'] = tuple(json_safe.values()) - json_safe['dict'] = json_safe.copy() - - json_unsafe = { - 'uuid_empty': lluuid.UUID(), - 'uuid_full': lluuid.UUID('dc61ab0530200d7554d23510559102c1a98aab1b'), - 'binary_empty': llsd.binary(), - 'binary': llsd.binary('f\0\xff'), - 'uri_empty': llsd.uri(), - 'uri': llsd.uri('http://www.secondlife.com/'), - 'datetime_empty': datetime.datetime(1970,1,1), - 'datetime': datetime.datetime(1999,9,9,9,9,9), - } - json_unsafe.update(json_safe) - json_unsafe['array'] = json_unsafe.values() - json_unsafe['tuple'] = tuple(json_unsafe.values()) - json_unsafe['dict'] = json_unsafe.copy() - json_unsafe['iter'] = iter(json_unsafe.values()) - - def _test_client_content_type_good(self, content_type, ll): - def run(ll): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.content_type = content_type - req.llsd = ll - req.accept = content_type - resp = req.get_response(self.server) - self.assertEquals(resp.status_int, 200) - return req, resp - - if False and isinstance(ll, dict): - def fixup(v): - if isinstance(v, float): - return '%.5f' % v - if isinstance(v, long): - return int(v) - if isinstance(v, (llsd.binary, llsd.uri)): - return v - if isinstance(v, (tuple, list)): - return [fixup(i) for i in v] - if isinstance(v, dict): - return dict([(k, fixup(i)) for k, i in v.iteritems()]) - return v - for k, v in ll.iteritems(): - l = [k, v] - req, resp = run(l) - self.assertEquals(fixup(resp.llsd), fixup(l)) - - run(ll) - - def test_client_content_type_json_good(self): - self._test_client_content_type_good('application/json', self.json_safe) - - def test_client_content_type_llsd_xml_good(self): - self._test_client_content_type_good('application/llsd+xml', - self.json_unsafe) - - def test_client_content_type_llsd_notation_good(self): - self._test_client_content_type_good('application/llsd+notation', - self.json_unsafe) - - def test_client_content_type_llsd_binary_good(self): - self._test_client_content_type_good('application/llsd+binary', - self.json_unsafe) - - def test_client_content_type_xml_good(self): - self._test_client_content_type_good('application/xml', - self.json_unsafe) - - def _test_client_content_type_bad(self, content_type): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.body = '\0invalid nonsense under all encodings' - req.content_type = content_type - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPBadRequest.code) - - def test_client_content_type_json_bad(self): - self._test_client_content_type_bad('application/json') - - def test_client_content_type_llsd_xml_bad(self): - self._test_client_content_type_bad('application/llsd+xml') - - def test_client_content_type_llsd_notation_bad(self): - self._test_client_content_type_bad('application/llsd+notation') - - def test_client_content_type_llsd_binary_bad(self): - self._test_client_content_type_bad('application/llsd+binary') - - def test_client_content_type_xml_bad(self): - self._test_client_content_type_bad('application/xml') - - def test_client_content_type_bad(self): - req = siesta.Request.blank('/') - req.environ['REQUEST_METHOD'] = 'POST' - req.body = 'XXX' - req.content_type = 'application/nonsense' - self.assertEquals(req.get_response(self.server).status_int, - exc.HTTPUnsupportedMediaType.code) - - def test_request_default_content_type(self): - req = siesta.Request.blank('/') - self.assertEquals(req.content_type, req.default_content_type) - - def test_request_default_accept(self): - req = siesta.Request.blank('/') - from webob import acceptparse - self.assertEquals(str(req.accept).replace(' ', ''), - req.default_accept.replace(' ', '')) - - def test_request_llsd_auto_body(self): - req = siesta.Request.blank('/') - req.llsd = {'a': 2} - self.assertEquals(req.body, '' - 'a2') - - def test_request_llsd_mod_body_changes_llsd(self): - req = siesta.Request.blank('/') - req.llsd = {'a': 2} - req.body = '1337' - self.assertEquals(req.llsd, 1337) - - def test_request_bad_llsd_fails(self): - def crashme(ctype): - def boom(): - class foo(object): pass - req = siesta.Request.blank('/') - req.content_type = ctype - req.llsd = foo() - for mime_type in siesta.llsd_parsers: - self.assertRaises(TypeError, crashme(mime_type)) - - -class ClassServer(TestBase, unittest.TestCase): - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) - self.server = siesta.llsd_class(ClassApp) - - -class CallableServer(TestBase, unittest.TestCase): - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) - self.server = siesta.llsd_callable(callable_app) - - -class RouterServer(unittest.TestCase): - def test_router(self): - def foo(req, quux): - print quux - - r = siesta.Router() - r.add('/foo/{quux:int}', siesta.llsd_callable(foo), methods=['GET']) - req = siesta.Request.blank('/foo/33') - req.get_response(r) - - req = siesta.Request.blank('/foo/bar') - self.assertEquals(req.get_response(r).status_int, - exc.HTTPNotFound.code) - -if __name__ == '__main__': - unittest.main() diff --git a/indra/lib/python/indra/ipc/tokenstream.py b/indra/lib/python/indra/ipc/tokenstream.py deleted file mode 100755 index b96f26d3ff..0000000000 --- a/indra/lib/python/indra/ipc/tokenstream.py +++ /dev/null @@ -1,154 +0,0 @@ -"""\ -@file tokenstream.py -@brief Message template parsing utility class - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import re - -class _EOF(object): - pass - -EOF = _EOF() - -class _LineMarker(int): - pass - -_commentRE = re.compile(r'//.*') -_symbolRE = re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*') -_integerRE = re.compile(r'(0x[0-9A-Fa-f]+|0\d*|[1-9]\d*)') -_floatRE = re.compile(r'\d+(\.\d*)?') - - -class ParseError(Exception): - def __init__(self, stream, reason): - self.line = stream.line - self.context = stream._context() - self.reason = reason - - def _contextString(self): - c = [ ] - for t in self.context: - if isinstance(t, _LineMarker): - break - c.append(t) - return " ".join(c) - - def __str__(self): - return "line %d: %s @ ... %s" % ( - self.line, self.reason, self._contextString()) - - def __nonzero__(self): - return False - - -def _optionText(options): - n = len(options) - if n == 1: - return '"%s"' % options[0] - return '"' + '", "'.join(options[0:(n-1)]) + '" or "' + options[-1] + '"' - - -class TokenStream(object): - def __init__(self): - self.line = 0 - self.tokens = [ ] - - def fromString(self, string): - return self.fromLines(string.split('\n')) - - def fromFile(self, file): - return self.fromLines(file) - - def fromLines(self, lines): - i = 0 - for line in lines: - i += 1 - self.tokens.append(_LineMarker(i)) - self.tokens.extend(_commentRE.sub(" ", line).split()) - self._consumeLines() - return self - - def consume(self): - if not self.tokens: - return EOF - t = self.tokens.pop(0) - self._consumeLines() - return t - - def _consumeLines(self): - while self.tokens and isinstance(self.tokens[0], _LineMarker): - self.line = self.tokens.pop(0) - - def peek(self): - if not self.tokens: - return EOF - return self.tokens[0] - - def want(self, t): - if t == self.peek(): - return self.consume() - return ParseError(self, 'expected "%s"' % t) - - def wantOneOf(self, options): - assert len(options) - if self.peek() in options: - return self.consume() - return ParseError(self, 'expected one of %s' % _optionText(options)) - - def wantEOF(self): - return self.want(EOF) - - def wantRE(self, re, message=None): - t = self.peek() - if t != EOF: - m = re.match(t) - if m and m.end() == len(t): - return self.consume() - if not message: - message = "expected match for r'%s'" % re.pattern - return ParseError(self, message) - - def wantSymbol(self): - return self.wantRE(_symbolRE, "expected symbol") - - def wantInteger(self): - return self.wantRE(_integerRE, "expected integer") - - def wantFloat(self): - return self.wantRE(_floatRE, "expected float") - - def _context(self): - n = min(5, len(self.tokens)) - return self.tokens[0:n] - - def require(self, t): - if t: - return t - if isinstance(t, ParseError): - raise t - else: - raise ParseError(self, "unmet requirement") - diff --git a/indra/lib/python/indra/ipc/webdav.py b/indra/lib/python/indra/ipc/webdav.py deleted file mode 100755 index 98b8499b6a..0000000000 --- a/indra/lib/python/indra/ipc/webdav.py +++ /dev/null @@ -1,597 +0,0 @@ -""" -@file webdav.py -@brief Classes to make manipulation of a webdav store easier. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, httplib, urlparse -import socket, time -import xml.dom.minidom -import syslog -# import signal - -__revision__ = '0' - -dav_debug = False - - -# def urlsafe_b64decode (enc): -# return base64.decodestring (enc.replace ('_', '/').replace ('-', '+')) - -# def urlsafe_b64encode (str): -# return base64.encodestring (str).replace ('+', '-').replace ('/', '_') - - -class DAVError (Exception): - """ Base class for exceptions in this module. """ - def __init__ (self, status=0, message='', body='', details=''): - self.status = status - self.message = message - self.body = body - self.details = details - Exception.__init__ (self, '%d:%s:%s%s' % (self.status, self.message, - self.body, self.details)) - - def print_to_stderr (self): - """ print_to_stderr docstring """ - print >> sys.stderr, str (self.status) + ' ' + self.message - print >> sys.stderr, str (self.details) - - -class Timeout (Exception): - """ Timeout docstring """ - def __init__ (self, arg=''): - Exception.__init__ (self, arg) - - -def alarm_handler (signum, frame): - """ alarm_handler docstring """ - raise Timeout ('caught alarm') - - -class WebDAV: - """ WebDAV docstring """ - def __init__ (self, url, proxy=None, retries_before_fail=6): - self.init_url = url - self.init_proxy = proxy - self.retries_before_fail = retries_before_fail - url_parsed = urlparse.urlsplit (url) - - self.top_path = url_parsed[ 2 ] - # make sure top_path has a trailing / - if self.top_path == None or self.top_path == '': - self.top_path = '/' - elif len (self.top_path) > 1 and self.top_path[-1:] != '/': - self.top_path += '/' - - if dav_debug: - syslog.syslog ('new WebDAV %s : %s' % (str (url), str (proxy))) - - if proxy: - proxy_parsed = urlparse.urlsplit (proxy) - self.host_header = url_parsed[ 1 ] - host_and_port = proxy_parsed[ 1 ].split (':') - self.host = host_and_port[ 0 ] - if len (host_and_port) > 1: - self.port = int(host_and_port[ 1 ]) - else: - self.port = 80 - else: # no proxy - host_and_port = url_parsed[ 1 ].split (':') - self.host_header = None - self.host = host_and_port[ 0 ] - if len (host_and_port) > 1: - self.port = int(host_and_port[ 1 ]) - else: - self.port = 80 - - self.connection = False - self.connect () - - - def log (self, msg, depth=0): - """ log docstring """ - if dav_debug and depth == 0: - host = str (self.init_url) - if host == 'http://int.tuco.lindenlab.com:80/asset/': - host = 'tuco' - if host == 'http://harriet.lindenlab.com/asset-keep/': - host = 'harriet/asset-keep' - if host == 'http://harriet.lindenlab.com/asset-flag/': - host = 'harriet/asset-flag' - if host == 'http://harriet.lindenlab.com/asset/': - host = 'harriet/asset' - if host == 'http://ozzy.lindenlab.com/asset/': - host = 'ozzy/asset' - if host == 'http://station11.lindenlab.com:12041/:': - host = 'station11:12041' - proxy = str (self.init_proxy) - if proxy == 'None': - proxy = '' - if proxy == 'http://int.tuco.lindenlab.com:3128/': - proxy = 'tuco' - syslog.syslog ('WebDAV (%s:%s) %s' % (host, proxy, str (msg))) - - - def connect (self): - """ connect docstring """ - self.log ('connect') - self.connection = httplib.HTTPConnection (self.host, self.port) - - def __err (self, response, details): - """ __err docstring """ - raise DAVError (response.status, response.reason, response.read (), - str (self.init_url) + ':' + \ - str (self.init_proxy) + ':' + str (details)) - - def request (self, method, path, body=None, headers=None, - read_all=True, body_hook = None, recurse=0, allow_cache=True): - """ request docstring """ - # self.log ('request %s %s' % (method, path)) - if headers == None: - headers = {} - if not allow_cache: - headers['Pragma'] = 'no-cache' - headers['cache-control'] = 'no-cache' - try: - if method.lower () != 'purge': - if path.startswith ('/'): - path = path[1:] - if self.host_header: # use proxy - headers[ 'host' ] = self.host_header - fullpath = 'http://%s%s%s' % (self.host_header, - self.top_path, path) - else: # no proxy - fullpath = self.top_path + path - else: - fullpath = path - - self.connection.request (method, fullpath, body, headers) - if body_hook: - body_hook () - - # signal.signal (signal.SIGALRM, alarm_handler) - # try: - # signal.alarm (120) - # signal.alarm (0) - # except Timeout, e: - # if recurse < 6: - # return self.retry_request (method, path, body, headers, - # read_all, body_hook, recurse) - # else: - # raise DAVError (0, 'timeout', self.host, - # (method, path, body, headers, recurse)) - - response = self.connection.getresponse () - - if read_all: - while len (response.read (1024)) > 0: - pass - if (response.status == 500 or \ - response.status == 503 or \ - response.status == 403) and \ - recurse < self.retries_before_fail: - return self.retry_request (method, path, body, headers, - read_all, body_hook, recurse) - return response - except (httplib.ResponseNotReady, - httplib.BadStatusLine, - socket.error): - # if the server hangs up on us (keepalive off, broken pipe), - # we need to reconnect and try again. - if recurse < self.retries_before_fail: - return self.retry_request (method, path, body, headers, - read_all, body_hook, recurse) - raise DAVError (0, 'reconnect failed', self.host, - (method, path, body, headers, recurse)) - - - def retry_request (self, method, path, body, headers, - read_all, body_hook, recurse): - """ retry_request docstring """ - time.sleep (10.0 * recurse) - self.connect () - return self.request (method, path, body, headers, - read_all, body_hook, recurse+1) - - - - def propfind (self, path, body=None, depth=1): - """ propfind docstring """ - # self.log ('propfind %s' % path) - headers = {'Content-Type':'text/xml; charset="utf-8"', - 'Depth':str(depth)} - response = self.request ('PROPFIND', path, body, headers, False) - if response.status == 207: - return response # Multi-Status - self.__err (response, ('PROPFIND', path, body, headers, 0)) - - - def purge (self, path): - """ issue a squid purge command """ - headers = {'Accept':'*/*'} - response = self.request ('PURGE', path, None, headers) - if response.status == 200 or response.status == 404: - # 200 if it was purge, 404 if it wasn't there. - return response - self.__err (response, ('PURGE', path, None, headers)) - - - def get_file_size (self, path): - """ - Use propfind to ask a webdav server what the size of - a file is. If used on a directory (collection) return 0 - """ - self.log ('get_file_size %s' % path) - # "getcontentlength" property - # 8.1.1 Example - Retrieving Named Properties - # http://docs.python.org/lib/module-xml.dom.html - nsurl = 'http://apache.org/dav/props/' - doc = xml.dom.minidom.Document () - propfind_element = doc.createElementNS (nsurl, "D:propfind") - propfind_element.setAttributeNS (nsurl, 'xmlns:D', 'DAV:') - doc.appendChild (propfind_element) - prop_element = doc.createElementNS (nsurl, "D:prop") - propfind_element.appendChild (prop_element) - con_len_element = doc.createElementNS (nsurl, "D:getcontentlength") - prop_element.appendChild (con_len_element) - - response = self.propfind (path, doc.toxml ()) - doc.unlink () - - resp_doc = xml.dom.minidom.parseString (response.read ()) - cln = resp_doc.getElementsByTagNameNS ('DAV:','getcontentlength')[ 0 ] - try: - content_length = int (cln.childNodes[ 0 ].nodeValue) - except IndexError: - return 0 - resp_doc.unlink () - return content_length - - - def file_exists (self, path): - """ - do an http head on the given file. return True if it succeeds - """ - self.log ('file_exists %s' % path) - expect_gzip = path.endswith ('.gz') - response = self.request ('HEAD', path) - got_gzip = response.getheader ('Content-Encoding', '').strip () - if got_gzip.lower () == 'x-gzip' and expect_gzip == False: - # the asset server fakes us out if we ask for the non-gzipped - # version of an asset, but the server has the gzipped version. - return False - return response.status == 200 - - - def mkdir (self, path): - """ mkdir docstring """ - self.log ('mkdir %s' % path) - headers = {} - response = self.request ('MKCOL', path, None, headers) - if response.status == 201: - return # success - if response.status == 405: - return # directory already existed? - self.__err (response, ('MKCOL', path, None, headers, 0)) - - - def delete (self, path): - """ delete docstring """ - self.log ('delete %s' % path) - headers = {'Depth':'infinity'} # collections require infinity - response = self.request ('DELETE', path, None, headers) - if response.status == 204: - return # no content - if response.status == 404: - return # hmm - self.__err (response, ('DELETE', path, None, headers, 0)) - - - def list_directory (self, path, dir_filter=None, allow_cache=True, - minimum_cache_time=False): - """ - Request an http directory listing and parse the filenames out of lines - like: '
  • X'. If a filter function is provided, - only return filenames that the filter returns True for. - - This is sort of grody, but it seems faster than other ways of getting - this information from an isilon. - """ - self.log ('list_directory %s' % path) - - def try_match (lline, before, after): - """ try_match docstring """ - try: - blen = len (before) - asset_start_index = lline.index (before) - asset_end_index = lline.index (after, asset_start_index + blen) - asset = line[ asset_start_index + blen : asset_end_index ] - - if not dir_filter or dir_filter (asset): - return [ asset ] - return [] - except ValueError: - return [] - - if len (path) > 0 and path[-1:] != '/': - path += '/' - - response = self.request ('GET', path, None, {}, False, - allow_cache=allow_cache) - - if allow_cache and minimum_cache_time: # XXX - print response.getheader ('Date') - # s = "2005-12-06T12:13:14" - # from datetime import datetime - # from time import strptime - # datetime(*strptime(s, "%Y-%m-%dT%H:%M:%S")[0:6]) - # datetime.datetime(2005, 12, 6, 12, 13, 14) - - if response.status != 200: - self.__err (response, ('GET', path, None, {}, 0)) - assets = [] - for line in response.read ().split ('\n'): - lline = line.lower () - if lline.find ("parent directory") == -1: - # isilon file - assets += try_match (lline, '
  • ') - # apache dir - assets += try_match (lline, 'alt="[dir]"> ') - # apache file - assets += try_match (lline, 'alt="[ ]"> ') - return assets - - - def __tmp_filename (self, path_and_file): - """ __tmp_filename docstring """ - head, tail = os.path.split (path_and_file) - if head != '': - return head + '/.' + tail + '.' + str (os.getpid ()) - else: - return head + '.' + tail + '.' + str (os.getpid ()) - - - def __put__ (self, filesize, body_hook, remotefile): - """ __put__ docstring """ - headers = {'Content-Length' : str (filesize)} - remotefile_tmp = self.__tmp_filename (remotefile) - response = self.request ('PUT', remotefile_tmp, None, - headers, True, body_hook) - if not response.status in (201, 204): # created, no content - self.__err (response, ('PUT', remotefile, None, headers, 0)) - if filesize != self.get_file_size (remotefile_tmp): - try: - self.delete (remotefile_tmp) - except: - pass - raise DAVError (0, 'tmp upload error', remotefile_tmp) - # move the file to its final location - try: - self.rename (remotefile_tmp, remotefile) - except DAVError, exc: - if exc.status == 403: # try to clean up the tmp file - try: - self.delete (remotefile_tmp) - except: - pass - raise - if filesize != self.get_file_size (remotefile): - raise DAVError (0, 'file upload error', str (remotefile_tmp)) - - - def put_string (self, strng, remotefile): - """ put_string docstring """ - self.log ('put_string %d -> %s' % (len (strng), remotefile)) - filesize = len (strng) - def body_hook (): - """ body_hook docstring """ - self.connection.send (strng) - self.__put__ (filesize, body_hook, remotefile) - - - def put_file (self, localfile, remotefile): - """ - Send a local file to a remote webdav store. First, upload to - a temporary filename. Next make sure the file is the size we - expected. Next, move the file to its final location. Next, - check the file size at the final location. - """ - self.log ('put_file %s -> %s' % (localfile, remotefile)) - filesize = os.path.getsize (localfile) - def body_hook (): - """ body_hook docstring """ - handle = open (localfile) - while True: - data = handle.read (1300) - if len (data) == 0: - break - self.connection.send (data) - handle.close () - self.__put__ (filesize, body_hook, remotefile) - - - def create_empty_file (self, remotefile): - """ create an empty file """ - self.log ('touch_file %s' % (remotefile)) - headers = {'Content-Length' : '0'} - response = self.request ('PUT', remotefile, None, headers) - if not response.status in (201, 204): # created, no content - self.__err (response, ('PUT', remotefile, None, headers, 0)) - if self.get_file_size (remotefile) != 0: - raise DAVError (0, 'file upload error', str (remotefile)) - - - def __get_file_setup (self, remotefile, check_size=True): - """ __get_file_setup docstring """ - if check_size: - remotesize = self.get_file_size (remotefile) - response = self.request ('GET', remotefile, None, {}, False) - if response.status != 200: - self.__err (response, ('GET', remotefile, None, {}, 0)) - try: - content_length = int (response.getheader ("Content-Length")) - except TypeError: - content_length = None - if check_size: - if content_length != remotesize: - raise DAVError (0, 'file DL size error', remotefile) - return (response, content_length) - - - def __get_file_read (self, writehandle, response, content_length): - """ __get_file_read docstring """ - if content_length != None: - so_far_length = 0 - while so_far_length < content_length: - data = response.read (content_length - so_far_length) - if len (data) == 0: - raise DAVError (0, 'short file download') - so_far_length += len (data) - writehandle.write (data) - while len (response.read ()) > 0: - pass - else: - while True: - data = response.read () - if (len (data) < 1): - break - writehandle.write (data) - - - def get_file (self, remotefile, localfile, check_size=True): - """ - Get a remote file from a webdav server. Download to a local - tmp file, then move into place. Sanity check file sizes as - we go. - """ - self.log ('get_file %s -> %s' % (remotefile, localfile)) - (response, content_length) = \ - self.__get_file_setup (remotefile, check_size) - localfile_tmp = self.__tmp_filename (localfile) - handle = open (localfile_tmp, 'w') - self.__get_file_read (handle, response, content_length) - handle.close () - if check_size: - if content_length != os.path.getsize (localfile_tmp): - raise DAVError (0, 'file DL size error', - remotefile+','+localfile) - os.rename (localfile_tmp, localfile) - - - def get_file_as_string (self, remotefile, check_size=True): - """ - download a file from a webdav server and return it as a string. - """ - self.log ('get_file_as_string %s' % remotefile) - (response, content_length) = \ - self.__get_file_setup (remotefile, check_size) - # (tmp_handle, tmp_filename) = tempfile.mkstemp () - tmp_handle = os.tmpfile () - self.__get_file_read (tmp_handle, response, content_length) - tmp_handle.seek (0) - ret = tmp_handle.read () - tmp_handle.close () - # os.unlink (tmp_filename) - return ret - - - def get_post_as_string (self, remotefile, body): - """ - Do an http POST, send body, get response and return it. - """ - self.log ('get_post_as_string %s' % remotefile) - # headers = {'Content-Type':'application/x-www-form-urlencoded'} - headers = {'Content-Type':'text/xml; charset="utf-8"'} - # b64body = urlsafe_b64encode (asset_url) - response = self.request ('POST', remotefile, body, headers, False) - if response.status != 200: - self.__err (response, ('POST', remotefile, body, headers, 0)) - try: - content_length = int (response.getheader ('Content-Length')) - except TypeError: - content_length = None - tmp_handle = os.tmpfile () - self.__get_file_read (tmp_handle, response, content_length) - tmp_handle.seek (0) - ret = tmp_handle.read () - tmp_handle.close () - return ret - - - def __destination_command (self, verb, remotesrc, dstdav, remotedst): - """ - self and dstdav should point to the same http server. - """ - if len (remotedst) > 0 and remotedst[ 0 ] == '/': - remotedst = remotedst[1:] - headers = {'Destination': 'http://%s:%d%s%s' % (dstdav.host, - dstdav.port, - dstdav.top_path, - remotedst)} - response = self.request (verb, remotesrc, None, headers) - if response.status == 201: - return # created - if response.status == 204: - return # no content - self.__err (response, (verb, remotesrc, None, headers, 0)) - - - def rename (self, remotesrc, remotedst): - """ rename a file on a webdav server """ - self.log ('rename %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('MOVE', remotesrc, self, remotedst) - def xrename (self, remotesrc, dstdav, remotedst): - """ rename a file on a webdav server """ - self.log ('xrename %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('MOVE', remotesrc, dstdav, remotedst) - - - def copy (self, remotesrc, remotedst): - """ copy a file on a webdav server """ - self.log ('copy %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('COPY', remotesrc, self, remotedst) - def xcopy (self, remotesrc, dstdav, remotedst): - """ copy a file on a webdav server """ - self.log ('xcopy %s -> %s' % (remotesrc, remotedst)) - self.__destination_command ('COPY', remotesrc, dstdav, remotedst) - - -def put_string (data, url): - """ - upload string s to a url - """ - url_parsed = urlparse.urlsplit (url) - dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ])) - dav.put_string (data, url_parsed[ 2 ]) - - -def get_string (url, check_size=True): - """ - return the contents of a url as a string - """ - url_parsed = urlparse.urlsplit (url) - dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ])) - return dav.get_file_as_string (url_parsed[ 2 ], check_size) diff --git a/indra/lib/python/indra/ipc/xml_rpc.py b/indra/lib/python/indra/ipc/xml_rpc.py deleted file mode 100755 index 47536c10c3..0000000000 --- a/indra/lib/python/indra/ipc/xml_rpc.py +++ /dev/null @@ -1,273 +0,0 @@ -"""\ -@file xml_rpc.py -@brief An implementation of a parser/generator for the XML-RPC xml format. - -$LicenseInfo:firstyear=2006&license=mit$ - -Copyright (c) 2006-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - - -from greenlet import greenlet - -from mulib import mu - -from xml.sax import handler -from xml.sax import parseString - - -# States -class Expected(object): - def __init__(self, tag): - self.tag = tag - - def __getattr__(self, name): - return type(self)(name) - - def __repr__(self): - return '%s(%r)' % ( - type(self).__name__, self.tag) - - -class START(Expected): - pass - - -class END(Expected): - pass - - -class STR(object): - tag = '' - - -START = START('') -END = END('') - - -class Malformed(Exception): - pass - - -class XMLParser(handler.ContentHandler): - def __init__(self, state_machine, next_states): - handler.ContentHandler.__init__(self) - self.state_machine = state_machine - if not isinstance(next_states, tuple): - next_states = (next_states, ) - self.next_states = next_states - self._character_buffer = '' - - def assertState(self, state, name, *rest): - if not isinstance(self.next_states, tuple): - self.next_states = (self.next_states, ) - for next in self.next_states: - if type(state) == type(next): - if next.tag and next.tag != name: - raise Malformed( - "Expected %s, got %s %s %s" % ( - next, state, name, rest)) - break - else: - raise Malformed( - "Expected %s, got %s %s %s" % ( - self.next_states, state, name, rest)) - - def startElement(self, name, attrs): - self.assertState(START, name.lower(), attrs) - self.next_states = self.state_machine.switch(START, (name.lower(), dict(attrs))) - - def endElement(self, name): - if self._character_buffer.strip(): - characters = self._character_buffer.strip() - self._character_buffer = '' - self.assertState(STR, characters) - self.next_states = self.state_machine.switch(characters) - self.assertState(END, name.lower()) - self.next_states = self.state_machine.switch(END, name.lower()) - - def error(self, exc): - self.bozo = 1 - self.exc = exc - - def fatalError(self, exc): - self.error(exc) - raise exc - - def characters(self, characters): - self._character_buffer += characters - - -def parse(what): - child = greenlet(xml_rpc) - me = greenlet.getcurrent() - startup_states = child.switch(me) - parser = XMLParser(child, startup_states) - try: - parseString(what, parser) - except Malformed: - print what - raise - return child.switch() - - -def xml_rpc(yielder): - yielder.switch(START.methodcall) - yielder.switch(START.methodname) - methodName = yielder.switch(STR) - yielder.switch(END.methodname) - - yielder.switch(START.params) - - root = None - params = [] - while True: - state, _ = yielder.switch(START.param, END.params) - if state == END: - break - - yielder.switch(START.value) - - params.append( - handle(yielder)) - - yielder.switch(END.value) - yielder.switch(END.param) - - yielder.switch(END.methodcall) - ## Resume parse - yielder.switch() - ## Return result to parse - return methodName.strip(), params - - -def handle(yielder): - _, (tag, attrs) = yielder.switch(START) - if tag in ['int', 'i4']: - result = int(yielder.switch(STR)) - elif tag == 'boolean': - result = bool(int(yielder.switch(STR))) - elif tag == 'string': - result = yielder.switch(STR) - elif tag == 'double': - result = float(yielder.switch(STR)) - elif tag == 'datetime.iso8601': - result = yielder.switch(STR) - elif tag == 'base64': - result = base64.b64decode(yielder.switch(STR)) - elif tag == 'struct': - result = {} - while True: - state, _ = yielder.switch(START.member, END.struct) - if state == END: - break - - yielder.switch(START.name) - key = yielder.switch(STR) - yielder.switch(END.name) - - yielder.switch(START.value) - result[key] = handle(yielder) - yielder.switch(END.value) - - yielder.switch(END.member) - ## We already handled above, don't want to handle it below - return result - elif tag == 'array': - result = [] - yielder.switch(START.data) - while True: - state, _ = yielder.switch(START.value, END.data) - if state == END: - break - - result.append(handle(yielder)) - - yielder.switch(END.value) - - yielder.switch(getattr(END, tag)) - - return result - - -VALUE = mu.tag_factory('value') -BOOLEAN = mu.tag_factory('boolean') -INT = mu.tag_factory('int') -STRUCT = mu.tag_factory('struct') -MEMBER = mu.tag_factory('member') -NAME = mu.tag_factory('name') -ARRAY = mu.tag_factory('array') -DATA = mu.tag_factory('data') -STRING = mu.tag_factory('string') -DOUBLE = mu.tag_factory('double') -METHODRESPONSE = mu.tag_factory('methodResponse') -PARAMS = mu.tag_factory('params') -PARAM = mu.tag_factory('param') - -mu.inline_elements['string'] = True -mu.inline_elements['boolean'] = True -mu.inline_elements['name'] = True - - -def _generate(something): - if isinstance(something, dict): - result = STRUCT() - for key, value in something.items(): - result[ - MEMBER[ - NAME[key], _generate(value)]] - return VALUE[result] - elif isinstance(something, list): - result = DATA() - for item in something: - result[_generate(item)] - return VALUE[ARRAY[[result]]] - elif isinstance(something, basestring): - return VALUE[STRING[something]] - elif isinstance(something, bool): - if something: - return VALUE[BOOLEAN['1']] - return VALUE[BOOLEAN['0']] - elif isinstance(something, int): - return VALUE[INT[something]] - elif isinstance(something, float): - return VALUE[DOUBLE[something]] - -def generate(*args): - params = PARAMS() - for arg in args: - params[PARAM[_generate(arg)]] - return METHODRESPONSE[params] - - -if __name__ == '__main__': - print parse(""" examples.getStateName 41 -""") - - - - - - - - - diff --git a/indra/lib/python/indra/util/fastest_elementtree.py b/indra/lib/python/indra/util/fastest_elementtree.py deleted file mode 100755 index 4fcf662dd9..0000000000 --- a/indra/lib/python/indra/util/fastest_elementtree.py +++ /dev/null @@ -1,64 +0,0 @@ -"""\ -@file fastest_elementtree.py -@brief Concealing some gnarly import logic in here. This should export the interface of elementtree. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -# The parsing exception raised by the underlying library depends -# on the ElementTree implementation we're using, so we provide an -# alias here. -# -# Use ElementTreeError as the exception type for catching parsing -# errors. - - -# Using cElementTree might cause some unforeseen problems, so here's a -# convenient off switch. -use_celementree = True - -try: - if not use_celementree: - raise ImportError() - # Python 2.3 and 2.4. - from cElementTree import * - ElementTreeError = SyntaxError -except ImportError: - try: - if not use_celementree: - raise ImportError() - # Python 2.5 and above. - from xml.etree.cElementTree import * - ElementTreeError = SyntaxError - except ImportError: - # Pure Python code. - try: - # Python 2.3 and 2.4. - from elementtree.ElementTree import * - except ImportError: - # Python 2.5 and above. - from xml.etree.ElementTree import * - - # The pure Python ElementTree module uses Expat for parsing. - from xml.parsers.expat import ExpatError as ElementTreeError diff --git a/indra/lib/python/indra/util/helpformatter.py b/indra/lib/python/indra/util/helpformatter.py deleted file mode 100755 index ba5c9b67d1..0000000000 --- a/indra/lib/python/indra/util/helpformatter.py +++ /dev/null @@ -1,52 +0,0 @@ -"""\ -@file helpformatter.py -@author Phoenix -@brief Class for formatting optparse descriptions. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import optparse -import textwrap - -class Formatter(optparse.IndentedHelpFormatter): - def __init__( - self, - p_indentIncrement = 2, - p_maxHelpPosition = 24, - p_width = 79, - p_shortFirst = 1) : - optparse.HelpFormatter.__init__( - self, - p_indentIncrement, - p_maxHelpPosition, - p_width, - p_shortFirst) - def format_description(self, p_description): - t_descWidth = self.width - self.current_indent - t_indent = " " * (self.current_indent + 2) - return "\n".join( - [textwrap.fill(descr, t_descWidth, initial_indent = t_indent, - subsequent_indent = t_indent) - for descr in p_description.split("\n")] ) diff --git a/indra/lib/python/indra/util/iterators.py b/indra/lib/python/indra/util/iterators.py deleted file mode 100755 index 9013fa6303..0000000000 --- a/indra/lib/python/indra/util/iterators.py +++ /dev/null @@ -1,63 +0,0 @@ -"""\ -@file iterators.py -@brief Useful general-purpose iterators. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -from __future__ import nested_scopes - -def iter_chunks(rows, aggregate_size=100): - """ - Given an iterable set of items (@p rows), produces lists of up to @p - aggregate_size items at a time, for example: - - iter_chunks([1,2,3,4,5,6,7,8,9,10], 3) - - Values for @p aggregate_size < 1 will raise ValueError. - - Will return a generator that produces, in the following order: - - [1, 2, 3] - - [4, 5, 6] - - [7, 8, 9] - - [10] - """ - if aggregate_size < 1: - raise ValueError() - - def iter_chunks_inner(): - row_iter = iter(rows) - done = False - agg = [] - while not done: - try: - row = row_iter.next() - agg.append(row) - except StopIteration: - done = True - if agg and (len(agg) >= aggregate_size or done): - yield agg - agg = [] - - return iter_chunks_inner() diff --git a/indra/lib/python/indra/util/iterators_test.py b/indra/lib/python/indra/util/iterators_test.py deleted file mode 100755 index 66928c8e7d..0000000000 --- a/indra/lib/python/indra/util/iterators_test.py +++ /dev/null @@ -1,72 +0,0 @@ -"""\ -@file iterators_test.py -@brief Test cases for iterators module. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import unittest - -from indra.util.iterators import iter_chunks - -class TestIterChunks(unittest.TestCase): - """Unittests for iter_chunks""" - def test_bad_agg_size(self): - rows = [1,2,3,4] - self.assertRaises(ValueError, iter_chunks, rows, 0) - self.assertRaises(ValueError, iter_chunks, rows, -1) - - try: - for i in iter_chunks(rows, 0): - pass - except ValueError: - pass - else: - self.fail() - - try: - result = list(iter_chunks(rows, 0)) - except ValueError: - pass - else: - self.fail() - def test_empty(self): - rows = [] - result = list(iter_chunks(rows)) - self.assertEqual(result, []) - def test_small(self): - rows = [[1]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1]]]) - def test_size(self): - rows = [[1],[2]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1],[2]]]) - def test_multi_agg(self): - rows = [[1],[2],[3],[4],[5]] - result = list(iter_chunks(rows, 2)) - self.assertEqual(result, [[[1],[2]],[[3],[4]],[[5]]]) - -if __name__ == "__main__": - unittest.main() diff --git a/indra/lib/python/indra/util/llperformance.py b/indra/lib/python/indra/util/llperformance.py deleted file mode 100755 index 57dd64de3f..0000000000 --- a/indra/lib/python/indra/util/llperformance.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python -"""\ -@file llperformance.py - -$LicenseInfo:firstyear=2010&license=viewerlgpl$ -Second Life Viewer Source Code -Copyright (C) 2010-2011, 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$ -""" - -# ------------------------------------------------ -# Sim metrics utility functions. - -import glob, os, time, sys, stat, exceptions - -from indra.base import llsd - -gBlockMap = {} #Map of performance metric data with function hierarchy information. -gCurrentStatPath = "" - -gIsLoggingEnabled=False - -class LLPerfStat: - def __init__(self,key): - self.mTotalTime = 0 - self.mNumRuns = 0 - self.mName=key - self.mTimeStamp = int(time.time()*1000) - self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - - def __str__(self): - return "%f" % self.mTotalTime - - def start(self): - self.mStartTime = int(time.time() * 1000000) - self.mNumRuns += 1 - - def stop(self): - execution_time = int(time.time() * 1000000) - self.mStartTime - self.mTotalTime += execution_time - - def get_map(self): - results={} - results['name']=self.mName - results['utc_time']=self.mUTCTime - results['timestamp']=self.mTimeStamp - results['us']=self.mTotalTime - results['count']=self.mNumRuns - return results - -class PerfError(exceptions.Exception): - def __init__(self): - return - - def __Str__(self): - print "","Unfinished LLPerfBlock" - -class LLPerfBlock: - def __init__( self, key ): - global gBlockMap - global gCurrentStatPath - global gIsLoggingEnabled - - #Check to see if we're running metrics right now. - if gIsLoggingEnabled: - self.mRunning = True #Mark myself as running. - - self.mPreviousStatPath = gCurrentStatPath - gCurrentStatPath += "/" + key - if gCurrentStatPath not in gBlockMap: - gBlockMap[gCurrentStatPath] = LLPerfStat(key) - - self.mStat = gBlockMap[gCurrentStatPath] - self.mStat.start() - - def finish( self ): - global gBlockMap - global gIsLoggingEnabled - - if gIsLoggingEnabled: - self.mStat.stop() - self.mRunning = False - gCurrentStatPath = self.mPreviousStatPath - -# def __del__( self ): -# if self.mRunning: -# #SPATTERS FIXME -# raise PerfError - -class LLPerformance: - #-------------------------------------------------- - # Determine whether or not we want to log statistics - - def __init__( self, process_name = "python" ): - self.process_name = process_name - self.init_testing() - self.mTimeStamp = int(time.time()*1000) - self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - - def init_testing( self ): - global gIsLoggingEnabled - - host_performance_file = "/dev/shm/simperf/simperf_proc_config.llsd" - - #If file exists, open - if os.path.exists(host_performance_file): - file = open (host_performance_file,'r') - - #Read serialized LLSD from file. - body = llsd.parse(file.read()) - - #Calculate time since file last modified. - stats = os.stat(host_performance_file) - now = time.time() - mod = stats[stat.ST_MTIME] - age = now - mod - - if age < ( body['duration'] ): - gIsLoggingEnabled = True - - - def get ( self ): - global gIsLoggingEnabled - return gIsLoggingEnabled - - #def output(self,ptr,path): - # if 'stats' in ptr: - # stats = ptr['stats'] - # self.mOutputPtr[path] = stats.get_map() - - # if 'children' in ptr: - # children=ptr['children'] - - # curptr = self.mOutputPtr - # curchildren={} - # curptr['children'] = curchildren - - # for key in children: - # curchildren[key]={} - # self.mOutputPtr = curchildren[key] - # self.output(children[key],path + '/' + key) - - def done(self): - global gBlockMap - - if not self.get(): - return - - output_name = "/dev/shm/simperf/%s_proc.%d.llsd" % (self.process_name, os.getpid()) - output_file = open(output_name, 'w') - process_info = { - "name" : self.process_name, - "pid" : os.getpid(), - "ppid" : os.getppid(), - "timestamp" : self.mTimeStamp, - "utc_time" : self.mUTCTime, - } - output_file.write(llsd.format_notation(process_info)) - output_file.write('\n') - - for key in gBlockMap.keys(): - gBlockMap[key] = gBlockMap[key].get_map() - output_file.write(llsd.format_notation(gBlockMap)) - output_file.write('\n') - output_file.close() - diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py deleted file mode 100755 index 7e0e115d14..0000000000 --- a/indra/lib/python/indra/util/llsubprocess.py +++ /dev/null @@ -1,117 +0,0 @@ -"""\ -@file llsubprocess.py -@author Phoenix -@date 2008-01-18 -@brief The simplest possible wrapper for a common sub-process paradigm. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import os -import popen2 -import time -import select - -class Timeout(RuntimeError): - "Exception raised when a subprocess times out." - pass - -def run(command, args=None, data=None, timeout=None): - """\ -@brief Run command with arguments - -This is it. This is the function I want to run all the time when doing -subprocces, but end up copying the code everywhere. none of the -standard commands are secure and provide a way to specify input, get -all the output, and get the result. -@param command A string specifying a process to launch. -@param args Arguments to be passed to command. Must be list, tuple or None. -@param data input to feed to the command. -@param timeout Maximum number of many seconds to run. -@return Returns (result, stdout, stderr) from process. -""" - cmd = [command] - if args: - cmd.extend([str(arg) for arg in args]) - #print "cmd: ","' '".join(cmd) - child = popen2.Popen3(cmd, True) - #print child.pid - out = [] - err = [] - result = -1 - time_left = timeout - tochild = [child.tochild.fileno()] - while True: - time_start = time.time() - #print "time:",time_left - p_in, p_out, p_err = select.select( - [child.fromchild.fileno(), child.childerr.fileno()], - tochild, - [], - time_left) - if p_in: - new_line = os.read(child.fromchild.fileno(), 32 * 1024) - if new_line: - #print "line:",new_line - out.append(new_line) - new_line = os.read(child.childerr.fileno(), 32 * 1024) - if new_line: - #print "error:", new_line - err.append(new_line) - if p_out: - if data: - #print "p_out" - bytes = os.write(child.tochild.fileno(), data) - data = data[bytes:] - if len(data) == 0: - data = None - tochild = [] - child.tochild.close() - result = child.poll() - if result != -1: - # At this point, the child process has exited and result - # is the return value from the process. Between the time - # we called select() and poll() the process may have - # exited so read all the data left on the child process - # stdout and stderr. - last = child.fromchild.read() - if last: - out.append(last) - last = child.childerr.read() - if last: - err.append(last) - child.tochild.close() - child.fromchild.close() - child.childerr.close() - break - if time_left is not None: - time_left -= (time.time() - time_start) - if time_left < 0: - raise Timeout - #print "result:",result - out = ''.join(out) - #print "stdout:", out - err = ''.join(err) - #print "stderr:", err - return result, out, err diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py deleted file mode 100755 index 6bf956107d..0000000000 --- a/indra/lib/python/indra/util/named_query.py +++ /dev/null @@ -1,592 +0,0 @@ -"""\ -@file named_query.py -@author Ryan Williams, Phoenix -@date 2007-07-31 -@brief An API for running named queries. - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import errno -import MySQLdb -import MySQLdb.cursors -import os -import os.path -import re -import time - -from indra.base import llsd -from indra.base import config - -DEBUG = False -NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') -NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) - -_g_named_manager = None - -def _init_g_named_manager(sql_dir = None): - """Initializes a global NamedManager object to point at a - specified named queries hierarchy. - - This function is intended entirely for testing purposes, - because it's tricky to control the config from inside a test.""" - global NQ_FILE_SUFFIX - NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') - global NQ_FILE_SUFFIX_LEN - NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) - - if sql_dir is None: - sql_dir = config.get('named-query-base-dir') - - # extra fallback directory in case config doesn't return what we want - if sql_dir is None: - sql_dir = os.path.abspath( - os.path.join( - os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql")) - - global _g_named_manager - _g_named_manager = NamedQueryManager( - os.path.abspath(os.path.realpath(sql_dir))) - -def get(name, schema = None): - "Get the named query object to be used to perform queries" - if _g_named_manager is None: - _init_g_named_manager() - return _g_named_manager.get(name).for_schema(schema) - -def sql(connection, name, params): - # use module-global NamedQuery object to perform default substitution - return get(name).sql(connection, params) - -def run(connection, name, params, expect_rows = None): - """\ -@brief given a connection, run a named query with the params - -Note that this function will fetch ALL rows. -@param connection The connection to use -@param name The name of the query to run -@param params The parameters passed into the query -@param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack. -@return Returns the result set as a list of dicts. -""" - return get(name).run(connection, params, expect_rows) - -class ExpectationFailed(Exception): - """ Exception that is raised when an expectation for an sql query - is not met.""" - def __init__(self, message): - Exception.__init__(self, message) - self.message = message - -class NamedQuery(object): - def __init__(self, name, filename): - """ Construct a NamedQuery object. The name argument is an - arbitrary name as a handle for the query, and the filename is - a path to a file or a file-like object containing an llsd named - query document.""" - self._stat_interval_seconds = 5 # 5 seconds - self._name = name - if (filename is not None and isinstance(filename, (str, unicode)) - and NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]): - filename = filename + NQ_FILE_SUFFIX - self._location = filename - self._alternative = dict() - self._last_mod_time = 0 - self._last_check_time = 0 - self.deleted = False - self.load_contents() - - def name(self): - """ The name of the query. """ - return self._name - - def get_modtime(self): - """ Returns the mtime (last modified time) of the named query - filename. For file-like objects, expect a modtime of 0""" - if self._location and isinstance(self._location, (str, unicode)): - return os.path.getmtime(self._location) - return 0 - - def load_contents(self): - """ Loads and parses the named query file into self. Does - nothing if self.location is nonexistant.""" - if self._location: - if isinstance(self._location, (str, unicode)): - contents = llsd.parse(open(self._location).read()) - else: - # we probably have a file-like object. Godspeed! - contents = llsd.parse(self._location.read()) - self._reference_contents(contents) - # Check for alternative implementations - try: - for name, alt in self._contents['alternative'].items(): - nq = NamedQuery(name, None) - nq._reference_contents(alt) - self._alternative[name] = nq - except KeyError, e: - pass - self._last_mod_time = self.get_modtime() - self._last_check_time = time.time() - - def _reference_contents(self, contents): - "Helper method which builds internal structure from parsed contents" - self._contents = contents - self._ttl = int(self._contents.get('ttl', 0)) - self._return_as_map = bool(self._contents.get('return_as_map', False)) - self._legacy_dbname = self._contents.get('legacy_dbname', None) - - # reset these before doing the sql conversion because we will - # read them there. reset these while loading so we pick up - # changes. - self._around = set() - self._append = set() - self._integer = set() - self._options = self._contents.get('dynamic_where', {}) - for key in self._options: - if isinstance(self._options[key], basestring): - self._options[key] = self._convert_sql(self._options[key]) - elif isinstance(self._options[key], list): - lines = [] - for line in self._options[key]: - lines.append(self._convert_sql(line)) - self._options[key] = lines - else: - moreopt = {} - for kk in self._options[key]: - moreopt[kk] = self._convert_sql(self._options[key][kk]) - self._options[key] = moreopt - self._base_query = self._convert_sql(self._contents['base_query']) - self._query_suffix = self._convert_sql( - self._contents.get('query_suffix', '')) - - def _convert_sql(self, sql): - """convert the parsed sql into a useful internal structure. - - This function has to turn the named query format into a pyformat - style. It also has to look for %:name% and :name% and - ready them for use in LIKE statements""" - if sql: - # This first sub is to properly escape any % signs that - # are meant to be literally passed through to mysql in the - # query. It leaves any %'s that are used for - # like-expressions. - expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])") - sql = expr.sub('%%', sql) - - # This should tackle the rest of the %'s in the query, by - # converting them to LIKE clauses. - expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") - sql = expr.sub(self._prepare_like, sql) - expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") - sql = expr.sub(self._prepare_integer, sql) - expr = re.compile(":([a-zA-Z][a-zA-Z0-9_-]*)") - sql = expr.sub("%(\\1)s", sql) - return sql - - def _prepare_like(self, match): - """This function changes LIKE statement replace behavior - - It works by turning %:name% to %(_name_around)s and :name% to - %(_name_append)s. Since a leading '_' is not a valid keyname - input (enforced via unit tests), it will never clash with - existing keys. Then, when building the statement, the query - runner will generate corrected strings.""" - if match.group(1) == '%': - # there is a leading % so this is treated as prefix/suffix - self._around.add(match.group(2)) - return "%(" + self._build_around_key(match.group(2)) + ")s" - else: - # there is no leading %, so this is suffix only - self._append.add(match.group(2)) - return "%(" + self._build_append_key(match.group(2)) + ")s" - - def _build_around_key(self, key): - return "_" + key + "_around" - - def _build_append_key(self, key): - return "_" + key + "_append" - - def _prepare_integer(self, match): - """This function adjusts the sql for #:name replacements - - It works by turning #:name to %(_name_as_integer)s. Since a - leading '_' is not a valid keyname input (enforced via unit - tests), it will never clash with existing keys. Then, when - building the statement, the query runner will generate - corrected strings.""" - self._integer.add(match.group(1)) - return "%(" + self._build_integer_key(match.group(1)) + ")s" - - def _build_integer_key(self, key): - return "_" + key + "_as_integer" - - def _strip_wildcards_to_list(self, value): - """Take string, and strip out the LIKE special characters. - - Technically, this is database dependant, but postgresql and - mysql use the same wildcards, and I am not aware of a general - way to handle this. I think you need a sql statement of the - form: - - LIKE_STRING( [ANY,ONE,str]... ) - - which would treat ANY as their any string, and ONE as their - single glyph, and str as something that needs database - specific encoding to not allow any % or _ to affect the query. - - As it stands, I believe it's impossible to write a named query - style interface which uses like to search the entire space of - text available. Imagine the query: - - % of brain used by average linden - - In order to search for %, it must be escaped, so once you have - escaped the string to not do wildcard searches, and be escaped - for the database, and then prepended the wildcard you come - back with one of: - - 1) %\% of brain used by average linden - 2) %%% of brain used by average linden - - Then, when passed to the database to be escaped to be database - safe, you get back: - - 1) %\\% of brain used by average linden - : which means search for any character sequence, followed by a - backslash, followed by any sequence, followed by ' of - brain...' - 2) %%% of brain used by average linden - : which (I believe) means search for a % followed by any - character sequence followed by 'of brain...' - - Neither of which is what we want! - - So, we need a vendor (or extention) for LIKE_STRING. Anyone - want to write it?""" - if isinstance(value, unicode): - utf8_value = value - else: - utf8_value = unicode(value, "utf-8") - esc_list = [] - remove_chars = set(u"%_") - for glyph in utf8_value: - if glyph in remove_chars: - continue - esc_list.append(glyph.encode("utf-8")) - return esc_list - - def delete(self): - """ Makes this query unusable by deleting all the members and - setting the deleted member. This is desired when the on-disk - query has been deleted but the in-memory copy remains.""" - # blow away all members except _name, _location, and deleted - name, location = self._name, self._location - for key in self.__dict__.keys(): - del self.__dict__[key] - self.deleted = True - self._name, self._location = name, location - - def ttl(self): - """ Estimated time to live of this query. Used for web - services to set the Expires header.""" - return self._ttl - - def legacy_dbname(self): - return self._legacy_dbname - - def return_as_map(self): - """ Returns true if this query is configured to return its - results as a single map (as opposed to a list of maps, the - normal behavior).""" - - return self._return_as_map - - def for_schema(self, db_name): - "Look trough the alternates and return the correct query" - if db_name is None: - return self - try: - return self._alternative[db_name] - except KeyError, e: - pass - return self - - def run(self, connection, params, expect_rows = None, use_dictcursor = True): - """given a connection, run a named query with the params - - Note that this function will fetch ALL rows. We do this because it - opens and closes the cursor to generate the values, and this - isn't a generator so the cursor has no life beyond the method call. - - @param cursor The connection to use (this generates its own cursor for the query) - @param name The name of the query to run - @param params The parameters passed into the query - @param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack. - @param use_dictcursor Set to false to use a normal cursor and manually convert the rows to dicts. - @return Returns the result set as a list of dicts, or, if the named query has return_as_map set to true, returns a single dict. - """ - if use_dictcursor: - cursor = connection.cursor(MySQLdb.cursors.DictCursor) - else: - cursor = connection.cursor() - - full_query, params = self._construct_sql(params) - if DEBUG: - print "SQL:", self.sql(connection, params) - rows = cursor.execute(full_query, params) - - # *NOTE: the expect_rows argument is a very cheesy way to get some - # validation on the result set. If you want to add more expectation - # logic, do something more object-oriented and flexible. Or use an ORM. - if(self._return_as_map): - expect_rows = 1 - if expect_rows is not None and rows != expect_rows: - cursor.close() - raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % ( - expect_rows, rows, full_query, params)) - - # convert to dicts manually if we're not using a dictcursor - if use_dictcursor: - result_set = cursor.fetchall() - else: - if cursor.description is None: - # an insert or something - x = cursor.fetchall() - cursor.close() - return x - - names = [x[0] for x in cursor.description] - - result_set = [] - for row in cursor.fetchall(): - converted_row = {} - for idx, col_name in enumerate(names): - converted_row[col_name] = row[idx] - result_set.append(converted_row) - - cursor.close() - if self._return_as_map: - return result_set[0] - return result_set - - def _construct_sql(self, params): - """ Returns a query string and a dictionary of parameters, - suitable for directly passing to the execute() method.""" - self.refresh() - - # build the query from the options available and the params - base_query = [] - base_query.append(self._base_query) - for opt, extra_where in self._options.items(): - if type(extra_where) in (dict, list, tuple): - if opt in params: - base_query.append(extra_where[params[opt]]) - else: - if opt in params and params[opt]: - base_query.append(extra_where) - if self._query_suffix: - base_query.append(self._query_suffix) - full_query = '\n'.join(base_query) - - # Go through the query and rewrite all of the ones with the - # @:name syntax. - rewrite = _RewriteQueryForArray(params) - expr = re.compile("@%\(([a-zA-Z][a-zA-Z0-9_-]*)\)s") - full_query = expr.sub(rewrite.operate, full_query) - params.update(rewrite.new_params) - - # build out the params for like. We only have to do this - # parameters which were detected to have ued the where syntax - # during load. - # - # * treat the incoming string as utf-8 - # * strip wildcards - # * append or prepend % as appropriate - new_params = {} - for key in params: - if key in self._around: - new_value = ['%'] - new_value.extend(self._strip_wildcards_to_list(params[key])) - new_value.append('%') - new_params[self._build_around_key(key)] = ''.join(new_value) - if key in self._append: - new_value = self._strip_wildcards_to_list(params[key]) - new_value.append('%') - new_params[self._build_append_key(key)] = ''.join(new_value) - if key in self._integer: - new_params[self._build_integer_key(key)] = int(params[key]) - params.update(new_params) - - return full_query, params - - def sql(self, connection, params): - """ Generates an SQL statement from the named query document - and a dictionary of parameters. - - *NOTE: Only use for debugging, because it uses the - non-standard MySQLdb 'literal' method. - """ - if not DEBUG: - import warnings - warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location) - # do substitution using the mysql (non-standard) 'literal' - # function to do the escaping. - full_query, params = self._construct_sql(params) - return full_query % connection.literal(params) - - - def refresh(self): - """ Refresh self from the file on the filesystem. - - This is optimized to be callable as frequently as you wish, - without adding too much load. It does so by only stat-ing the - file every N seconds, where N defaults to 5 and is - configurable through the member _stat_interval_seconds. If the stat - reveals that the file has changed, refresh will re-parse the - contents of the file and use them to update the named query - instance. If the stat reveals that the file has been deleted, - refresh will call self.delete to make the in-memory - representation unusable.""" - now = time.time() - if(now - self._last_check_time > self._stat_interval_seconds): - self._last_check_time = now - try: - modtime = self.get_modtime() - if(modtime > self._last_mod_time): - self.load_contents() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - self.delete() # clean up self - raise # pass the exception along to the caller so they know that this query disappeared - -class NamedQueryManager(object): - """ Manages the lifespan of NamedQuery objects, drawing from a - directory hierarchy of named query documents. - - In practice this amounts to a memory cache of NamedQuery objects.""" - - def __init__(self, named_queries_dir): - """ Initializes a manager to look for named queries in a - directory.""" - self._dir = os.path.abspath(os.path.realpath(named_queries_dir)) - self._cached_queries = {} - - def sql(self, connection, name, params): - nq = self.get(name) - return nq.sql(connection, params) - - def get(self, name): - """ Returns a NamedQuery instance based on the name, either - from memory cache, or by parsing from disk. - - The name is simply a relative path to the directory associated - with the manager object. Before returning the instance, the - NamedQuery object is cached in memory, so that subsequent - accesses don't have to read from disk or do any parsing. This - means that NamedQuery objects returned by this method are - shared across all users of the manager object. - NamedQuery.refresh is used to bring the NamedQuery objects in - sync with the actual files on disk.""" - nq = self._cached_queries.get(name) - if nq is None: - nq = NamedQuery(name, os.path.join(self._dir, name)) - self._cached_queries[name] = nq - else: - try: - nq.refresh() - except OSError, e: - if e.errno == errno.ENOENT: # file not found - del self._cached_queries[name] - raise # pass exception along to caller so they know that the query disappeared - - return nq - -class _RewriteQueryForArray(object): - "Helper class for rewriting queries with the @:name syntax" - def __init__(self, params): - self.params = params - self.new_params = dict() - - def operate(self, match): - "Given a match, return the string that should be in use" - key = match.group(1) - value = self.params[key] - if type(value) in (list,tuple): - rv = [] - for idx in range(len(value)): - # if the value@idx is array-like, we are - # probably dealing with a VALUES - new_key = "_%s_%s"%(key, str(idx)) - val_item = value[idx] - if type(val_item) in (list, tuple, dict): - if type(val_item) is dict: - # this is because in Python, the order of - # key, value retrieval from the dict is not - # guaranteed to match what the input intended - # and for VALUES, order is important. - # TODO: Implemented ordered dict in LLSD parser? - raise ExpectationFailed('Only lists/tuples allowed,\ - received dict') - values_keys = [] - for value_idx, item in enumerate(val_item): - # we want a key of the format : - # key_#replacement_#value_row_#value_col - # ugh... so if we are replacing 10 rows in user_note, - # the first values clause would read (for @:user_notes) :- - # ( :_user_notes_0_1_1, :_user_notes_0_1_2, :_user_notes_0_1_3 ) - # the input LLSD for VALUES will look like: - # ... - # - # user_notes - # - # - # ... - # ... - # ... - # - # ... - # - # - # ... - values_key = "%s_%s"%(new_key, value_idx) - self.new_params[values_key] = item - values_keys.append("%%(%s)s"%values_key) - # now collapse all these new place holders enclosed in () - # from [':_key_0_1_1', ':_key_0_1_2', ':_key_0_1_3,...] - # rv will have [ '(:_key_0_1_1, :_key_0_1_2, :_key_0_1_3)', ] - # which is flattened a few lines below join(rv) - rv.append('(%s)' % ','.join(values_keys)) - else: - self.new_params[new_key] = val_item - rv.append("%%(%s)s"%new_key) - return ','.join(rv) - else: - # not something that can be expanded, so just drop the - # leading @ in the front of the match. This will mean that - # the single value we have, be it a string, int, whatever - # (other than dict) will correctly show up, eg: - # - # where foo in (@:foobar) -- foobar is a string, so we get - # where foo in (:foobar) - return match.group(0)[1:] diff --git a/indra/lib/python/indra/util/shutil2.py b/indra/lib/python/indra/util/shutil2.py deleted file mode 100755 index 9e2e7a6ded..0000000000 --- a/indra/lib/python/indra/util/shutil2.py +++ /dev/null @@ -1,84 +0,0 @@ -''' -@file shutil2.py -@brief a better shutil.copytree replacement - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -''' - -# -# shutil2.py -# Taken from http://www.scons.org/wiki/AccumulateBuilder -# the stock copytree sucks because it insists that the -# target dir not exist -# - -import os.path -import shutil - -def copytree(src, dest, symlinks=False): - """My own copyTree which does not fail if the directory exists. - - Recursively copy a directory tree using copy2(). - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. - - Behavior is meant to be identical to GNU 'cp -R'. - """ - def copyItems(src, dest, symlinks=False): - """Function that does all the work. - - It is necessary to handle the two 'cp' cases: - - destination does exist - - destination does not exist - - See 'cp -R' documentation for more details - """ - for item in os.listdir(src): - srcPath = os.path.join(src, item) - if os.path.isdir(srcPath): - srcBasename = os.path.basename(srcPath) - destDirPath = os.path.join(dest, srcBasename) - if not os.path.exists(destDirPath): - os.makedirs(destDirPath) - copyItems(srcPath, destDirPath) - elif os.path.islink(item) and symlinks: - linkto = os.readlink(item) - os.symlink(linkto, dest) - else: - shutil.copy2(srcPath, dest) - - # case 'cp -R src/ dest/' where dest/ already exists - if os.path.exists(dest): - destPath = os.path.join(dest, os.path.basename(src)) - if not os.path.exists(destPath): - os.makedirs(destPath) - # case 'cp -R src/ dest/' where dest/ does not exist - else: - os.makedirs(dest) - destPath = dest - # actually copy the files - copyItems(src, destPath) diff --git a/indra/lib/python/indra/util/simperf_host_xml_parser.py b/indra/lib/python/indra/util/simperf_host_xml_parser.py deleted file mode 100755 index 672c1050c2..0000000000 --- a/indra/lib/python/indra/util/simperf_host_xml_parser.py +++ /dev/null @@ -1,338 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_host_xml_parser.py -@brief Digest collector's XML dump and convert to simple dict/list structure - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, getopt, time -import simplejson -from xml import sax - - -def usage(): - print "Usage:" - print sys.argv[0] + " [options]" - print " Convert RRD's XML dump to JSON. Script to convert the simperf_host_collector-" - print " generated RRD dump into JSON. Steps include converting selected named" - print " fields from GAUGE type to COUNTER type by computing delta with preceding" - print " values. Top-level named fields are:" - print - print " lastupdate Time (javascript timestamp) of last data sample" - print " step Time in seconds between samples" - print " ds Data specification (name/type) for each column" - print " database Table of data samples, one time step per row" - print - print "Options:" - print " -i, --in Input settings filename. (Default: stdin)" - print " -o, --out Output settings filename. (Default: stdout)" - print " -h, --help Print this message and exit." - print - print "Example: %s -i rrddump.xml -o rrddump.json" % sys.argv[0] - print - print "Interfaces:" - print " class SimPerfHostXMLParser() # SAX content handler" - print " def simperf_host_xml_fixup(parser) # post-parse value fixup" - -class SimPerfHostXMLParser(sax.handler.ContentHandler): - - def __init__(self): - pass - - def startDocument(self): - self.rrd_last_update = 0 # public - self.rrd_step = 0 # public - self.rrd_ds = [] # public - self.rrd_records = [] # public - self._rrd_level = 0 - self._rrd_parse_state = 0 - self._rrd_chars = "" - self._rrd_capture = False - self._rrd_ds_val = {} - self._rrd_data_row = [] - self._rrd_data_row_has_nan = False - - def endDocument(self): - pass - - # Nasty little ad-hoc state machine to extract the elements that are - # necessary from the 'rrdtool dump' XML output. The same element - # name '' is used for two different data sets so we need to pay - # some attention to the actual structure to get the ones we want - # and ignore the ones we don't. - - def startElement(self, name, attrs): - self._rrd_level = self._rrd_level + 1 - self._rrd_capture = False - if self._rrd_level == 1: - if name == "rrd" and self._rrd_parse_state == 0: - self._rrd_parse_state = 1 # In - self._rrd_capture = True - self._rrd_chars = "" - elif self._rrd_level == 2: - if self._rrd_parse_state == 1: - if name == "lastupdate": - self._rrd_parse_state = 2 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "step": - self._rrd_parse_state = 3 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "ds": - self._rrd_parse_state = 4 # In - self._rrd_ds_val = {} - self._rrd_chars = "" - elif name == "rra": - self._rrd_parse_state = 5 # In - elif self._rrd_level == 3: - if self._rrd_parse_state == 4: - if name == "name": - self._rrd_parse_state = 6 # In - self._rrd_capture = True - self._rrd_chars = "" - elif name == "type": - self._rrd_parse_state = 7 # In - self._rrd_capture = True - self._rrd_chars = "" - elif self._rrd_parse_state == 5: - if name == "database": - self._rrd_parse_state = 8 # In - elif self._rrd_level == 4: - if self._rrd_parse_state == 8: - if name == "row": - self._rrd_parse_state = 9 # In - self._rrd_data_row = [] - self._rrd_data_row_has_nan = False - elif self._rrd_level == 5: - if self._rrd_parse_state == 9: - if name == "v": - self._rrd_parse_state = 10 # In - self._rrd_capture = True - self._rrd_chars = "" - - def endElement(self, name): - self._rrd_capture = False - if self._rrd_parse_state == 10: - self._rrd_capture = self._rrd_level == 6 - if self._rrd_level == 5: - if self._rrd_chars == "NaN": - self._rrd_data_row_has_nan = True - else: - self._rrd_data_row.append(self._rrd_chars) - self._rrd_parse_state = 9 # In - elif self._rrd_parse_state == 9: - if self._rrd_level == 4: - if not self._rrd_data_row_has_nan: - self.rrd_records.append(self._rrd_data_row) - self._rrd_parse_state = 8 # In - elif self._rrd_parse_state == 8: - if self._rrd_level == 3: - self._rrd_parse_state = 5 # In - elif self._rrd_parse_state == 7: - if self._rrd_level == 3: - self._rrd_ds_val["type"] = self._rrd_chars - self._rrd_parse_state = 4 # In - elif self._rrd_parse_state == 6: - if self._rrd_level == 3: - self._rrd_ds_val["name"] = self._rrd_chars - self._rrd_parse_state = 4 # In - elif self._rrd_parse_state == 5: - if self._rrd_level == 2: - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 4: - if self._rrd_level == 2: - self.rrd_ds.append(self._rrd_ds_val) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 3: - if self._rrd_level == 2: - self.rrd_step = long(self._rrd_chars) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 2: - if self._rrd_level == 2: - self.rrd_last_update = long(self._rrd_chars) - self._rrd_parse_state = 1 # In - elif self._rrd_parse_state == 1: - if self._rrd_level == 1: - self._rrd_parse_state = 0 # At top - - if self._rrd_level: - self._rrd_level = self._rrd_level - 1 - - def characters(self, content): - if self._rrd_capture: - self._rrd_chars = self._rrd_chars + content.strip() - -def _make_numeric(value): - try: - value = float(value) - except: - value = "" - return value - -def simperf_host_xml_fixup(parser, filter_start_time = None, filter_end_time = None): - # Fixup for GAUGE fields that are really COUNTS. They - # were forced to GAUGE to try to disable rrdtool's - # data interpolation/extrapolation for non-uniform time - # samples. - fixup_tags = [ "cpu_user", - "cpu_nice", - "cpu_sys", - "cpu_idle", - "cpu_waitio", - "cpu_intr", - # "file_active", - # "file_free", - # "inode_active", - # "inode_free", - "netif_in_kb", - "netif_in_pkts", - "netif_in_errs", - "netif_in_drop", - "netif_out_kb", - "netif_out_pkts", - "netif_out_errs", - "netif_out_drop", - "vm_page_in", - "vm_page_out", - "vm_swap_in", - "vm_swap_out", - #"vm_mem_total", - #"vm_mem_used", - #"vm_mem_active", - #"vm_mem_inactive", - #"vm_mem_free", - #"vm_mem_buffer", - #"vm_swap_cache", - #"vm_swap_total", - #"vm_swap_used", - #"vm_swap_free", - "cpu_interrupts", - "cpu_switches", - "cpu_forks" ] - - col_count = len(parser.rrd_ds) - row_count = len(parser.rrd_records) - - # Process the last row separately, just to make all values numeric. - for j in range(col_count): - parser.rrd_records[row_count - 1][j] = _make_numeric(parser.rrd_records[row_count - 1][j]) - - # Process all other row/columns. - last_different_row = row_count - 1 - current_row = row_count - 2 - while current_row >= 0: - # Check for a different value than the previous row. If everything is the same - # then this is probably just a filler/bogus entry. - is_different = False - for j in range(col_count): - parser.rrd_records[current_row][j] = _make_numeric(parser.rrd_records[current_row][j]) - if parser.rrd_records[current_row][j] != parser.rrd_records[last_different_row][j]: - # We're good. This is a different row. - is_different = True - - if not is_different: - # This is a filler/bogus entry. Just ignore it. - for j in range(col_count): - parser.rrd_records[current_row][j] = float('nan') - else: - # Some tags need to be converted into deltas. - for j in range(col_count): - if parser.rrd_ds[j]["name"] in fixup_tags: - parser.rrd_records[last_different_row][j] = \ - parser.rrd_records[last_different_row][j] - parser.rrd_records[current_row][j] - last_different_row = current_row - - current_row -= 1 - - # Set fixup_tags in the first row to 'nan' since they aren't useful anymore. - for j in range(col_count): - if parser.rrd_ds[j]["name"] in fixup_tags: - parser.rrd_records[0][j] = float('nan') - - # Add a timestamp to each row and to the catalog. Format and name - # chosen to match other simulator logging (hopefully). - start_time = parser.rrd_last_update - (parser.rrd_step * (row_count - 1)) - # Build a filtered list of rrd_records if we are limited to a time range. - filter_records = False - if filter_start_time is not None or filter_end_time is not None: - filter_records = True - filtered_rrd_records = [] - if filter_start_time is None: - filter_start_time = start_time * 1000 - if filter_end_time is None: - filter_end_time = parser.rrd_last_update * 1000 - - for i in range(row_count): - record_timestamp = (start_time + (i * parser.rrd_step)) * 1000 - parser.rrd_records[i].insert(0, record_timestamp) - if filter_records: - if filter_start_time <= record_timestamp and record_timestamp <= filter_end_time: - filtered_rrd_records.append(parser.rrd_records[i]) - - if filter_records: - parser.rrd_records = filtered_rrd_records - - parser.rrd_ds.insert(0, {"type": "GAUGE", "name": "javascript_timestamp"}) - - -def main(argv=None): - opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"]) - input_file = sys.stdin - output_file = sys.stdout - for o, a in opts: - if o in ("-i", "--in"): - input_file = open(a, 'r') - if o in ("-o", "--out"): - output_file = open(a, 'w') - if o in ("-h", "--help"): - usage() - sys.exit(0) - - # Using the SAX parser as it is at least 4X faster and far, far - # smaller on this dataset than the DOM-based interface in xml.dom.minidom. - # With SAX and a 5.4MB xml file, this requires about seven seconds of - # wall-clock time and 32MB VSZ. With the DOM interface, about 22 seconds - # and over 270MB VSZ. - - handler = SimPerfHostXMLParser() - sax.parse(input_file, handler) - if input_file != sys.stdin: - input_file.close() - - # Various format fixups: string-to-num, gauge-to-counts, add - # a time stamp, etc. - simperf_host_xml_fixup(handler) - - # Create JSONable dict with interesting data and format/print it - print >>output_file, simplejson.dumps({ "step" : handler.rrd_step, - "lastupdate": handler.rrd_last_update * 1000, - "ds" : handler.rrd_ds, - "database" : handler.rrd_records }) - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/indra/lib/python/indra/util/simperf_oprof_interface.py b/indra/lib/python/indra/util/simperf_oprof_interface.py deleted file mode 100755 index 547d2f9980..0000000000 --- a/indra/lib/python/indra/util/simperf_oprof_interface.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_oprof_interface.py -@brief Manage OProfile data collection on a host - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -import sys, os, getopt -import simplejson - - -def usage(): - print "Usage:" - print sys.argv[0] + " [options]" - print " Digest the OProfile report forms that come out of the" - print " simperf_oprof_ctl program's -r/--report command. The result" - print " is an array of dictionaires with the following keys:" - print - print " symbol Name of sampled, calling, or called procedure" - print " file Executable or library where symbol resides" - print " percentage Percentage contribution to profile, calls or called" - print " samples Sample count" - print " calls Methods called by the method in question (full only)" - print " called_by Methods calling the method (full only)" - print - print " For 'full' reports the two keys 'calls' and 'called_by' are" - print " themselves arrays of dictionaries based on the first four keys." - print - print "Return Codes:" - print " None. Aggressively digests everything. Will likely mung results" - print " if a program or library has whitespace in its name." - print - print "Options:" - print " -i, --in Input settings filename. (Default: stdin)" - print " -o, --out Output settings filename. (Default: stdout)" - print " -h, --help Print this message and exit." - print - print "Interfaces:" - print " class SimPerfOProfileInterface()" - -class SimPerfOProfileInterface: - def __init__(self): - self.isBrief = True # public - self.isValid = False # public - self.result = [] # public - - def parse(self, input): - in_samples = False - for line in input: - if in_samples: - if line[0:6] == "------": - self.isBrief = False - self._parseFull(input) - else: - self._parseBrief(input, line) - self.isValid = True - return - try: - hd1, remain = line.split(None, 1) - if hd1 == "samples": - in_samples = True - except ValueError: - pass - - def _parseBrief(self, input, line1): - try: - fld1, fld2, fld3, fld4 = line1.split(None, 3) - self.result.append({"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")}) - except ValueError: - pass - for line in input: - try: - fld1, fld2, fld3, fld4 = line.split(None, 3) - self.result.append({"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")}) - except ValueError: - pass - - def _parseFull(self, input): - state = 0 # In 'called_by' section - calls = [] - called_by = [] - current = {} - for line in input: - if line[0:6] == "------": - if len(current): - current["calls"] = calls - current["called_by"] = called_by - self.result.append(current) - state = 0 - calls = [] - called_by = [] - current = {} - else: - try: - fld1, fld2, fld3, fld4 = line.split(None, 3) - tmp = {"samples" : fld1, - "percentage" : fld2, - "file" : fld3, - "symbol" : fld4.strip("\n")} - except ValueError: - continue - if line[0] != " ": - current = tmp - state = 1 # In 'calls' section - elif state == 0: - called_by.append(tmp) - else: - calls.append(tmp) - if len(current): - current["calls"] = calls - current["called_by"] = called_by - self.result.append(current) - - -def main(argv=None): - opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"]) - input_file = sys.stdin - output_file = sys.stdout - for o, a in opts: - if o in ("-i", "--in"): - input_file = open(a, 'r') - if o in ("-o", "--out"): - output_file = open(a, 'w') - if o in ("-h", "--help"): - usage() - sys.exit(0) - - oprof = SimPerfOProfileInterface() - oprof.parse(input_file) - if input_file != sys.stdin: - input_file.close() - - # Create JSONable dict with interesting data and format/print it - print >>output_file, simplejson.dumps(oprof.result) - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/indra/lib/python/indra/util/simperf_proc_interface.py b/indra/lib/python/indra/util/simperf_proc_interface.py deleted file mode 100755 index de061f68cc..0000000000 --- a/indra/lib/python/indra/util/simperf_proc_interface.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python -"""\ -@file simperf_proc_interface.py -@brief Utility to extract log messages from *..llsd files containing performance statistics. - -$LicenseInfo:firstyear=2008&license=mit$ - -Copyright (c) 2008-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -""" - -# ---------------------------------------------------- -# Utility to extract log messages from *..llsd -# files that contain performance statistics. - -# ---------------------------------------------------- -import sys, os - -if os.path.exists("setup-path.py"): - execfile("setup-path.py") - -from indra.base import llsd - -DEFAULT_PATH="/dev/shm/simperf/" - - -# ---------------------------------------------------- -# Pull out the stats and return a single document -def parse_logfile(filename, target_column=None, verbose=False): - full_doc = [] - # Open source temp log file. Let exceptions percolate up. - sourcefile = open( filename,'r') - - if verbose: - print "Reading " + filename - - # Parse and output all lines from the temp file - for line in sourcefile.xreadlines(): - partial_doc = llsd.parse(line) - if partial_doc is not None: - if target_column is None: - full_doc.append(partial_doc) - else: - trim_doc = { target_column: partial_doc[target_column] } - if target_column != "fps": - trim_doc[ 'fps' ] = partial_doc[ 'fps' ] - trim_doc[ '/total_time' ] = partial_doc[ '/total_time' ] - trim_doc[ 'utc_time' ] = partial_doc[ 'utc_time' ] - full_doc.append(trim_doc) - - sourcefile.close() - return full_doc - -# Extract just the meta info line, and the timestamp of the first/last frame entry. -def parse_logfile_info(filename, verbose=False): - # Open source temp log file. Let exceptions percolate up. - sourcefile = open(filename, 'rU') # U is to open with Universal newline support - - if verbose: - print "Reading " + filename - - # The first line is the meta info line. - info_line = sourcefile.readline() - if not info_line: - sourcefile.close() - return None - - # The rest of the lines are frames. Read the first and last to get the time range. - info = llsd.parse( info_line ) - info['start_time'] = None - info['end_time'] = None - first_frame = sourcefile.readline() - if first_frame: - try: - info['start_time'] = int(llsd.parse(first_frame)['timestamp']) - except: - pass - - # Read the file backwards to find the last two lines. - sourcefile.seek(0, 2) - file_size = sourcefile.tell() - offset = 1024 - num_attempts = 0 - end_time = None - if file_size < offset: - offset = file_size - while 1: - sourcefile.seek(-1*offset, 2) - read_str = sourcefile.read(offset) - # Remove newline at the end - if read_str[offset - 1] == '\n': - read_str = read_str[0:-1] - lines = read_str.split('\n') - full_line = None - if len(lines) > 2: # Got two line - try: - end_time = llsd.parse(lines[-1])['timestamp'] - except: - # We couldn't parse this line. Try once more. - try: - end_time = llsd.parse(lines[-2])['timestamp'] - except: - # Nope. Just move on. - pass - break - if len(read_str) == file_size: # Reached the beginning - break - offset += 1024 - - info['end_time'] = int(end_time) - - sourcefile.close() - return info - - -def parse_proc_filename(filename): - try: - name_as_list = filename.split(".") - cur_stat_type = name_as_list[0].split("_")[0] - cur_pid = name_as_list[1] - except IndexError, ValueError: - return (None, None) - return (cur_pid, cur_stat_type) - -# ---------------------------------------------------- -def get_simstats_list(path=None): - """ Return stats (pid, type) listed in _proc..llsd """ - if path is None: - path = DEFAULT_PATH - simstats_list = [] - for file_name in os.listdir(path): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - simstats_info = parse_logfile_info(path + file_name) - if simstats_info is not None: - simstats_list.append(simstats_info) - return simstats_list - -def get_log_info_list(pid=None, stat_type=None, path=None, target_column=None, verbose=False): - """ Return data from all llsd files matching the pid and stat type """ - if path is None: - path = DEFAULT_PATH - log_info_list = {} - for file_name in os.listdir ( path ): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - (cur_pid, cur_stat_type) = parse_proc_filename(file_name) - if cur_pid is None: - continue - if pid is not None and pid != cur_pid: - continue - if stat_type is not None and stat_type != cur_stat_type: - continue - log_info_list[cur_pid] = parse_logfile(path + file_name, target_column, verbose) - return log_info_list - -def delete_simstats_files(pid=None, stat_type=None, path=None): - """ Delete *..llsd files """ - if path is None: - path = DEFAULT_PATH - del_list = [] - for file_name in os.listdir(path): - if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd": - (cur_pid, cur_stat_type) = parse_proc_filename(file_name) - if cur_pid is None: - continue - if pid is not None and pid != cur_pid: - continue - if stat_type is not None and stat_type != cur_stat_type: - continue - del_list.append(cur_pid) - # Allow delete related exceptions to percolate up if this fails. - os.unlink(os.path.join(DEFAULT_PATH, file_name)) - return del_list - diff --git a/indra/lib/python/indra/util/term.py b/indra/lib/python/indra/util/term.py deleted file mode 100755 index 8c316a1f12..0000000000 --- a/indra/lib/python/indra/util/term.py +++ /dev/null @@ -1,222 +0,0 @@ -''' -@file term.py -@brief a better shutil.copytree replacement - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-2009, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -$/LicenseInfo$ -''' - -#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116 - -import sys, re - -class TerminalController: - """ - A class that can be used to portably generate formatted output to - a terminal. - - `TerminalController` defines a set of instance variables whose - values are initialized to the control sequence necessary to - perform a given action. These can be simply included in normal - output to the terminal: - - >>> term = TerminalController() - >>> print 'This is '+term.GREEN+'green'+term.NORMAL - - Alternatively, the `render()` method can used, which replaces - '${action}' with the string required to perform 'action': - - >>> term = TerminalController() - >>> print term.render('This is ${GREEN}green${NORMAL}') - - If the terminal doesn't support a given action, then the value of - the corresponding instance variable will be set to ''. As a - result, the above code will still work on terminals that do not - support color, except that their output will not be colored. - Also, this means that you can test whether the terminal supports a - given action by simply testing the truth value of the - corresponding instance variable: - - >>> term = TerminalController() - >>> if term.CLEAR_SCREEN: - ... print 'This terminal supports clearning the screen.' - - Finally, if the width and height of the terminal are known, then - they will be stored in the `COLS` and `LINES` attributes. - """ - # Cursor movement: - BOL = '' #: Move the cursor to the beginning of the line - UP = '' #: Move the cursor up one line - DOWN = '' #: Move the cursor down one line - LEFT = '' #: Move the cursor left one char - RIGHT = '' #: Move the cursor right one char - - # Deletion: - CLEAR_SCREEN = '' #: Clear the screen and move to home position - CLEAR_EOL = '' #: Clear to the end of the line. - CLEAR_BOL = '' #: Clear to the beginning of the line. - CLEAR_EOS = '' #: Clear to the end of the screen - - # Output modes: - BOLD = '' #: Turn on bold mode - BLINK = '' #: Turn on blink mode - DIM = '' #: Turn on half-bright mode - REVERSE = '' #: Turn on reverse-video mode - NORMAL = '' #: Turn off all modes - - # Cursor display: - HIDE_CURSOR = '' #: Make the cursor invisible - SHOW_CURSOR = '' #: Make the cursor visible - - # Terminal size: - COLS = None #: Width of the terminal (None for unknown) - LINES = None #: Height of the terminal (None for unknown) - - # Foreground colors: - BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = '' - - # Background colors: - BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = '' - BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = '' - - _STRING_CAPABILITIES = """ - BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1 - CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold - BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0 - HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split() - _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split() - _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split() - - def __init__(self, term_stream=sys.stdout): - """ - Create a `TerminalController` and initialize its attributes - with appropriate values for the current terminal. - `term_stream` is the stream that will be used for terminal - output; if this stream is not a tty, then the terminal is - assumed to be a dumb terminal (i.e., have no capabilities). - """ - # Curses isn't available on all platforms - try: import curses - except: return - - # If the stream isn't a tty, then assume it has no capabilities. - if not term_stream.isatty(): return - - # Check the terminal type. If we fail, then assume that the - # terminal has no capabilities. - try: curses.setupterm() - except: return - - # Look up numeric capabilities. - self.COLS = curses.tigetnum('cols') - self.LINES = curses.tigetnum('lines') - - # Look up string capabilities. - for capability in self._STRING_CAPABILITIES: - (attrib, cap_name) = capability.split('=') - setattr(self, attrib, self._tigetstr(cap_name) or '') - - # Colors - set_fg = self._tigetstr('setf') - if set_fg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, color, curses.tparm(set_fg, i) or '') - set_fg_ansi = self._tigetstr('setaf') - if set_fg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, color, curses.tparm(set_fg_ansi, i) or '') - set_bg = self._tigetstr('setb') - if set_bg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '') - set_bg_ansi = self._tigetstr('setab') - if set_bg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '') - - def _tigetstr(self, cap_name): - # String capabilities can include "delays" of the form "$<2>". - # For any modern terminal, we should be able to just ignore - # these, so strip them out. - import curses - cap = curses.tigetstr(cap_name) or '' - return re.sub(r'\$<\d+>[/*]?', '', cap) - - def render(self, template): - """ - Replace each $-substitutions in the given template string with - the corresponding terminal control string (if it's defined) or - '' (if it's not). - """ - return re.sub(r'\$\$|\${\w+}', self._render_sub, template) - - def _render_sub(self, match): - s = match.group() - if s == '$$': return s - else: return getattr(self, s[2:-1]) - -####################################################################### -# Example use case: progress bar -####################################################################### - -class ProgressBar: - """ - A 3-line progress bar, which looks like:: - - Header - 20% [===========----------------------------------] - progress message - - The progress bar is colored, if the terminal supports color - output; and adjusts to the width of the terminal. - """ - BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n' - HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n' - - def __init__(self, term, header): - self.term = term - if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL): - raise ValueError("Terminal isn't capable enough -- you " - "should use a simpler progress dispaly.") - self.width = self.term.COLS or 75 - self.bar = term.render(self.BAR) - self.header = self.term.render(self.HEADER % header.center(self.width)) - self.cleared = 1 #: true if we haven't drawn the bar yet. - self.update(0, '') - - def update(self, percent, message): - if self.cleared: - sys.stdout.write(self.header) - self.cleared = 0 - n = int((self.width-10)*percent) - sys.stdout.write( - self.term.BOL + self.term.UP + self.term.CLEAR_EOL + - (self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) + - self.term.CLEAR_EOL + message.center(self.width)) - - def clear(self): - if not self.cleared: - sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL) - self.cleared = 1 diff --git a/indra/lib/python/uuid.py b/indra/lib/python/uuid.py deleted file mode 100755 index e956383cca..0000000000 --- a/indra/lib/python/uuid.py +++ /dev/null @@ -1,508 +0,0 @@ -#!/usr/bin/python -## $LicenseInfo:firstyear=2011&license=viewerlgpl$ -## Second Life Viewer Source Code -## Copyright (C) 2011, 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$ -r"""UUID objects (universally unique identifiers) according to RFC 4122. - -This module provides immutable UUID objects (class UUID) and the functions -uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 -UUIDs as specified in RFC 4122. - -If all you want is a unique ID, you should probably call uuid1() or uuid4(). -Note that uuid1() may compromise privacy since it creates a UUID containing -the computer's network address. uuid4() creates a random UUID. - -Typical usage: - - >>> import uuid - - # make a UUID based on the host ID and current time - >>> uuid.uuid1() - UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') - - # make a UUID using an MD5 hash of a namespace UUID and a name - >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') - UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') - - # make a random UUID - >>> uuid.uuid4() - UUID('16fd2706-8baf-433b-82eb-8c7fada847da') - - # make a UUID using a SHA-1 hash of a namespace UUID and a name - >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') - UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') - - # make a UUID from a string of hex digits (braces and hyphens ignored) - >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') - - # convert a UUID to a string of hex digits in standard form - >>> str(x) - '00010203-0405-0607-0809-0a0b0c0d0e0f' - - # get the raw 16 bytes of the UUID - >>> x.bytes - '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' - - # make a UUID from a 16-byte string - >>> uuid.UUID(bytes=x.bytes) - UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') - -This module works with Python 2.3 or higher.""" - -__author__ = 'Ka-Ping Yee ' -__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-') -__version__ = '$Revision: 1.30 $'.split()[1] - -RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ - 'reserved for NCS compatibility', 'specified in RFC 4122', - 'reserved for Microsoft compatibility', 'reserved for future definition'] - -class UUID(object): - """Instances of the UUID class represent UUIDs as specified in RFC 4122. - UUID objects are immutable, hashable, and usable as dictionary keys. - Converting a UUID to a string with str() yields something in the form - '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts - four possible forms: a similar string of hexadecimal digits, or a - string of 16 raw bytes as an argument named 'bytes', or a tuple of - six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and - 48-bit values respectively) as an argument named 'fields', or a single - 128-bit integer as an argument named 'int'. - - UUIDs have these read-only attributes: - - bytes the UUID as a 16-byte string - - fields a tuple of the six integer fields of the UUID, - which are also available as six individual attributes - and two derived attributes: - - time_low the first 32 bits of the UUID - time_mid the next 16 bits of the UUID - time_hi_version the next 16 bits of the UUID - clock_seq_hi_variant the next 8 bits of the UUID - clock_seq_low the next 8 bits of the UUID - node the last 48 bits of the UUID - - time the 60-bit timestamp - clock_seq the 14-bit sequence number - - hex the UUID as a 32-character hexadecimal string - - int the UUID as a 128-bit integer - - urn the UUID as a URN as specified in RFC 4122 - - variant the UUID variant (one of the constants RESERVED_NCS, - RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) - - version the UUID version number (1 through 5, meaningful only - when the variant is RFC_4122) - """ - - def __init__(self, hex=None, bytes=None, fields=None, int=None, - version=None): - r"""Create a UUID from either a string of 32 hexadecimal digits, - a string of 16 bytes as the 'bytes' argument, a tuple of six - integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, - 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as - the 'fields' argument, or a single 128-bit integer as the 'int' - argument. When a string of hex digits is given, curly braces, - hyphens, and a URN prefix are all optional. For example, these - expressions all yield the same UUID: - - UUID('{12345678-1234-5678-1234-567812345678}') - UUID('12345678123456781234567812345678') - UUID('urn:uuid:12345678-1234-5678-1234-567812345678') - UUID(bytes='\x12\x34\x56\x78'*4) - UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) - UUID(int=0x12345678123456781234567812345678) - - Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. - The 'version' argument is optional; if given, the resulting UUID - will have its variant and version number set according to RFC 4122, - overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. - """ - - if [hex, bytes, fields, int].count(None) != 3: - raise TypeError('need just one of hex, bytes, fields, or int') - if hex is not None: - hex = hex.replace('urn:', '').replace('uuid:', '') - hex = hex.strip('{}').replace('-', '') - if len(hex) != 32: - raise ValueError('badly formed hexadecimal UUID string') - int = long(hex, 16) - if bytes is not None: - if len(bytes) != 16: - raise ValueError('bytes is not a 16-char string') - int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) - if fields is not None: - if len(fields) != 6: - raise ValueError('fields is not a 6-tuple') - (time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node) = fields - if not 0 <= time_low < 1<<32L: - raise ValueError('field 1 out of range (need a 32-bit value)') - if not 0 <= time_mid < 1<<16L: - raise ValueError('field 2 out of range (need a 16-bit value)') - if not 0 <= time_hi_version < 1<<16L: - raise ValueError('field 3 out of range (need a 16-bit value)') - if not 0 <= clock_seq_hi_variant < 1<<8L: - raise ValueError('field 4 out of range (need an 8-bit value)') - if not 0 <= clock_seq_low < 1<<8L: - raise ValueError('field 5 out of range (need an 8-bit value)') - if not 0 <= node < 1<<48L: - raise ValueError('field 6 out of range (need a 48-bit value)') - clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low - int = ((time_low << 96L) | (time_mid << 80L) | - (time_hi_version << 64L) | (clock_seq << 48L) | node) - if int is not None: - if not 0 <= int < 1<<128L: - raise ValueError('int is out of range (need a 128-bit value)') - if version is not None: - if not 1 <= version <= 5: - raise ValueError('illegal version number') - # Set the variant to RFC 4122. - int &= ~(0xc000 << 48L) - int |= 0x8000 << 48L - # Set the version number. - int &= ~(0xf000 << 64L) - int |= version << 76L - self.__dict__['int'] = int - - def __cmp__(self, other): - if isinstance(other, UUID): - return cmp(self.int, other.int) - return NotImplemented - - def __hash__(self): - return hash(self.int) - - def __int__(self): - return self.int - - def __repr__(self): - return 'UUID(%r)' % str(self) - - def __setattr__(self, name, value): - raise TypeError('UUID objects are immutable') - - def __str__(self): - hex = '%032x' % self.int - return '%s-%s-%s-%s-%s' % ( - hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) - - def get_bytes(self): - bytes = '' - for shift in range(0, 128, 8): - bytes = chr((self.int >> shift) & 0xff) + bytes - return bytes - - bytes = property(get_bytes) - - def get_fields(self): - return (self.time_low, self.time_mid, self.time_hi_version, - self.clock_seq_hi_variant, self.clock_seq_low, self.node) - - fields = property(get_fields) - - def get_time_low(self): - return self.int >> 96L - - time_low = property(get_time_low) - - def get_time_mid(self): - return (self.int >> 80L) & 0xffff - - time_mid = property(get_time_mid) - - def get_time_hi_version(self): - return (self.int >> 64L) & 0xffff - - time_hi_version = property(get_time_hi_version) - - def get_clock_seq_hi_variant(self): - return (self.int >> 56L) & 0xff - - clock_seq_hi_variant = property(get_clock_seq_hi_variant) - - def get_clock_seq_low(self): - return (self.int >> 48L) & 0xff - - clock_seq_low = property(get_clock_seq_low) - - def get_time(self): - return (((self.time_hi_version & 0x0fffL) << 48L) | - (self.time_mid << 32L) | self.time_low) - - time = property(get_time) - - def get_clock_seq(self): - return (((self.clock_seq_hi_variant & 0x3fL) << 8L) | - self.clock_seq_low) - - clock_seq = property(get_clock_seq) - - def get_node(self): - return self.int & 0xffffffffffff - - node = property(get_node) - - def get_hex(self): - return '%032x' % self.int - - hex = property(get_hex) - - def get_urn(self): - return 'urn:uuid:' + str(self) - - urn = property(get_urn) - - def get_variant(self): - if not self.int & (0x8000 << 48L): - return RESERVED_NCS - elif not self.int & (0x4000 << 48L): - return RFC_4122 - elif not self.int & (0x2000 << 48L): - return RESERVED_MICROSOFT - else: - return RESERVED_FUTURE - - variant = property(get_variant) - - def get_version(self): - # The version bits are only meaningful for RFC 4122 UUIDs. - if self.variant == RFC_4122: - return int((self.int >> 76L) & 0xf) - - version = property(get_version) - -def _ifconfig_getnode(): - """Get the hardware address on Unix by running ifconfig.""" - import os - for dir in ['', '/sbin/', '/usr/sbin']: - try: - path = os.path.join(dir, 'ifconfig') - if os.path.exists(path): - pipe = os.popen(path) - else: - continue - except IOError: - continue - for line in pipe: - words = line.lower().split() - for i in range(len(words)): - if words[i] in ['hwaddr', 'ether']: - return int(words[i + 1].replace(':', ''), 16) - -def _ipconfig_getnode(): - """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re - dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] - try: - import ctypes - buffer = ctypes.create_string_buffer(300) - ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) - dirs.insert(0, buffer.value.decode('mbcs')) - except: - pass - for dir in dirs: - try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') - except IOError: - continue - for line in pipe: - value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): - return int(value.replace('-', ''), 16) - -def _netbios_getnode(): - """Get the hardware address on Windows using NetBIOS calls. - See http://support.microsoft.com/kb/118623 for details.""" - import win32wnet, netbios - ncb = netbios.NCB() - ncb.Command = netbios.NCBENUM - ncb.Buffer = adapters = netbios.LANA_ENUM() - adapters._pack() - if win32wnet.Netbios(ncb) != 0: - return - adapters._unpack() - for i in range(adapters.length): - ncb.Reset() - ncb.Command = netbios.NCBRESET - ncb.Lana_num = ord(adapters.lana[i]) - if win32wnet.Netbios(ncb) != 0: - continue - ncb.Reset() - ncb.Command = netbios.NCBASTAT - ncb.Lana_num = ord(adapters.lana[i]) - ncb.Callname = '*'.ljust(16) - ncb.Buffer = status = netbios.ADAPTER_STATUS() - if win32wnet.Netbios(ncb) != 0: - continue - status._unpack() - bytes = map(ord, status.adapter_address) - return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + - (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) - -# Thanks to Thomas Heller for ctypes and for his help with its use here. - -# If ctypes is available, use it to find system routines for UUID generation. -_uuid_generate_random = _uuid_generate_time = _UuidCreate = None -try: - import ctypes, ctypes.util - _buffer = ctypes.create_string_buffer(16) - - # The uuid_generate_* routines are provided by libuuid on at least - # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: - try: - lib = ctypes.CDLL(ctypes.util.find_library(libname)) - except: - continue - if hasattr(lib, 'uuid_generate_random'): - _uuid_generate_random = lib.uuid_generate_random - if hasattr(lib, 'uuid_generate_time'): - _uuid_generate_time = lib.uuid_generate_time - - # On Windows prior to 2000, UuidCreate gives a UUID containing the - # hardware address. On Windows 2000 and later, UuidCreate makes a - # random UUID and UuidCreateSequential gives a UUID containing the - # hardware address. These routines are provided by the RPC runtime. - try: - lib = ctypes.windll.rpcrt4 - except: - lib = None - _UuidCreate = getattr(lib, 'UuidCreateSequential', - getattr(lib, 'UuidCreate', None)) -except: - pass - -def _unixdll_getnode(): - """Get the hardware address on Unix using ctypes.""" - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw).node - -def _windll_getnode(): - """Get the hardware address on Windows using ctypes.""" - if _UuidCreate(_buffer) == 0: - return UUID(bytes=_buffer.raw).node - -def _random_getnode(): - """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" - import random - return random.randrange(0, 1<<48L) | 0x010000000000L - -_node = None - -def getnode(): - """Get the hardware address as a 48-bit integer. The first time this - runs, it may launch a separate program, which could be quite slow. If - all attempts to obtain the hardware address fail, we choose a random - 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.""" - - global _node - if _node is not None: - return _node - - import sys - if sys.platform == 'win32': - getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] - else: - getters = [_unixdll_getnode, _ifconfig_getnode] - - for getter in getters + [_random_getnode]: - try: - _node = getter() - except: - continue - if _node is not None: - return _node - -def uuid1(node=None, clock_seq=None): - """Generate a UUID from a host ID, sequence number, and the current time. - If 'node' is not given, getnode() is used to obtain the hardware - address. If 'clock_seq' is given, it is used as the sequence number; - otherwise a random 14-bit sequence number is chosen.""" - - # When the system provides a version-1 UUID generator, use it (but don't - # use UuidCreate here because its UUIDs don't conform to RFC 4122). - if _uuid_generate_time and node is clock_seq is None: - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw) - - import time - nanoseconds = int(time.time() * 1e9) - # 0x01b21dd213814000 is the number of 100-ns intervals between the - # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. - timestamp = int(nanoseconds/100) + 0x01b21dd213814000L - if clock_seq is None: - import random - clock_seq = random.randrange(1<<14L) # instead of stable storage - time_low = timestamp & 0xffffffffL - time_mid = (timestamp >> 32L) & 0xffffL - time_hi_version = (timestamp >> 48L) & 0x0fffL - clock_seq_low = clock_seq & 0xffL - clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL - if node is None: - node = getnode() - return UUID(fields=(time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node), version=1) - -def uuid3(namespace, name): - """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" - try: - # Python 2.6 - from hashlib import md5 - except ImportError: - # Python 2.5 and earlier - from md5 import new as md5 - - hash = md5(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=3) - -def uuid4(): - """Generate a random UUID.""" - - # When the system provides a version-4 UUID generator, use it. - if _uuid_generate_random: - _uuid_generate_random(_buffer) - return UUID(bytes=_buffer.raw) - - # Otherwise, get randomness from urandom or the 'random' module. - try: - import os - return UUID(bytes=os.urandom(16), version=4) - except: - import random - bytes = [chr(random.randrange(256)) for i in range(16)] - return UUID(bytes=bytes, version=4) - -def uuid5(namespace, name): - """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" - import sha - hash = sha.sha(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=5) - -# The following standard UUIDs are for use with uuid3() or uuid5(). - -NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') -- cgit v1.2.3 From 9e93d24b201d0c43370b278a5bb7f1a2facabc30 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Wed, 20 Jul 2016 15:57:53 -0700 Subject: MAINT=6585: fix llsdserialize_test --- indra/llcommon/tests/llsdserialize_test.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 6fbb9abfc0..81b930e1e2 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -1518,10 +1518,7 @@ namespace tut // scanner. import_llsd("import os.path\n" "import sys\n" - "sys.path.insert(0,\n" - " os.path.join(os.path.dirname(r'" __FILE__ "'),\n" - " os.pardir, os.pardir, 'lib', 'python'))\n" - "from indra.base import llsd\n") + "from llbase import llsd\n") {} ~TestPythonCompatible() {} -- cgit v1.2.3 From 8a25489591d6f7c6c8aa95c98bbdcfe06d075c00 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Wed, 20 Jul 2016 19:54:54 -0700 Subject: MAINT-6578 Broken texture batching - fixed along with misc LibVLC plugin additions (status, titles, looping) --- indra/media_plugins/base/media_plugin_base.cpp | 1 + indra/media_plugins/base/media_plugin_base.h | 3 +- indra/media_plugins/cef/media_plugin_cef.cpp | 4 +- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 635 +++++++++++++-------- indra/newview/llmediactrl.cpp | 2 +- 5 files changed, 408 insertions(+), 237 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp index 37c498664a..a813d5f465 100644 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/media_plugins/base/media_plugin_base.cpp @@ -73,6 +73,7 @@ std::string MediaPluginBase::statusString() case STATUS_PLAYING: result = "playing"; break; case STATUS_PAUSED: result = "paused"; break; case STATUS_DONE: result = "done"; break; + case STATUS_BUFFERING: result = "buffering"; break; default: // keep the empty string break; diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h index 38b8226bb3..99bc49fc70 100644 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/media_plugins/base/media_plugin_base.h @@ -56,7 +56,8 @@ protected: STATUS_ERROR, STATUS_PLAYING, STATUS_PAUSED, - STATUS_DONE + STATUS_DONE, + STATUS_BUFFERING } EStatus; /** Plugin shared memory. */ diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index be16ff7946..28a8a5886a 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -189,7 +189,7 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, mPopupH = height; mPopupW = width; mPopupX = x; - mPopupY = y; + mPopupY = mHeight - y - height; } } else @@ -526,7 +526,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueU32("internalformat", GL_RGB); message.setValueU32("format", GL_BGRA); message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", false); + message.setValueBoolean("coords_opengl", true); sendMessage(message); } else if (message_name == "set_user_data_path") diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 8ef4ee2a27..f2e8252d3a 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -1,30 +1,30 @@ /** - * @file media_plugin_libvlc.cpp - * @brief LibVLC plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2008&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$ - * @endcond - */ +* @file media_plugin_libvlc.cpp +* @brief LibVLC plugin for LLMedia API plugin system +* +* @cond +* $LicenseInfo:firstyear=2008&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$ +* @endcond +*/ #include "linden_common.h" @@ -40,61 +40,78 @@ //////////////////////////////////////////////////////////////////////////////// // class MediaPluginLibVLC : - public MediaPluginBase + public MediaPluginBase { - public: - MediaPluginLibVLC( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); - ~MediaPluginLibVLC(); +public: + MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginLibVLC(); - /*virtual*/ void receiveMessage( const char* message_string ); + /*virtual*/ void receiveMessage(const char* message_string); - private: - bool init(); +private: + bool init(); - void initVLC(); - void playMedia(); - void resetVLC(); - void setVolume(const F64 volume); + void initVLC(); + void playMedia(); + void resetVLC(); + void setVolume(const F64 volume); + void updateTitle(const char* title); - static void* lock(void* data, void** p_pixels); - static void unlock(void* data, void* id, void* const* raw_pixels); - static void display(void* data, void* id); + static void* lock(void* data, void** p_pixels); + static void unlock(void* data, void* id, void* const* raw_pixels); + static void display(void* data, void* id); - libvlc_instance_t* gLibVLC; - libvlc_media_t* gLibVLCMedia; - libvlc_media_player_t* gLibVLCMediaPlayer; + /*virtual*/ void setDirty(int left, int top, int right, int bottom) override; - struct gVLCContext - { - unsigned char* texture_pixels; - libvlc_media_player_t* mp; - MediaPluginLibVLC* parent; - }; - struct gVLCContext gVLCCallbackContext; + static void eventCallbacks(const libvlc_event_t* event, void* ptr); + + libvlc_instance_t* mLibVLC; + libvlc_media_t* mLibVLCMedia; + libvlc_media_player_t* mLibVLCMediaPlayer; + + struct mLibVLCContext + { + unsigned char* texture_pixels; + libvlc_media_player_t* mp; + MediaPluginLibVLC* parent; + }; + struct mLibVLCContext mLibVLCCallbackContext; + + std::string mURL; + F64 mCurVolume; + + bool mIsLooping; - std::string mURL; - F64 mCurVolume; + float mCurTime; + float mDuration; }; //////////////////////////////////////////////////////////////////////////////// // -MediaPluginLibVLC::MediaPluginLibVLC( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : - MediaPluginBase( host_send_func, host_user_data ) +MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) { mTextureWidth = 0; mTextureHeight = 0; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; - gLibVLC = 0; - gLibVLCMedia = 0; - gLibVLCMediaPlayer = 0; + mLibVLC = 0; + mLibVLCMedia = 0; + mLibVLCMediaPlayer = 0; mCurVolume = 0.0; + mIsLooping = false; + + mCurTime = 0.0; + mDuration = 0.0; + mURL = std::string(); + + setStatus(STATUS_NONE); } //////////////////////////////////////////////////////////////////////////////// @@ -107,7 +124,7 @@ MediaPluginLibVLC::~MediaPluginLibVLC() // void* MediaPluginLibVLC::lock(void* data, void** p_pixels) { - struct gVLCContext* context = (gVLCContext*)data; + struct mLibVLCContext* context = (mLibVLCContext*)data; *p_pixels = context->texture_pixels; @@ -118,15 +135,16 @@ void* MediaPluginLibVLC::lock(void* data, void** p_pixels) // void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels) { - // nothing to do here for the moment. - // we can modify the raw_pixels here if we want to. + // nothing to do here for the moment + // we *could* modify pixels here to, for example, Y flip, but this is done with + // a VLC video filter transform. } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::display(void* data, void* id) { - struct gVLCContext* context = (gVLCContext*)data; + struct mLibVLCContext* context = (mLibVLCContext*)data; context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight); } @@ -138,12 +156,13 @@ void MediaPluginLibVLC::initVLC() char const* vlc_argv[] = { "--no-xlib", + "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client }; int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); - gLibVLC = libvlc_new(vlc_argc, vlc_argv); + mLibVLC = libvlc_new(vlc_argc, vlc_argv); - if (!gLibVLC) + if (!mLibVLC) { // for the moment, if this fails, the plugin will fail and // the media sub-system will tell the viewer something went wrong. @@ -154,9 +173,91 @@ void MediaPluginLibVLC::initVLC() // void MediaPluginLibVLC::resetVLC() { - libvlc_media_player_stop(gLibVLCMediaPlayer); - libvlc_media_player_release(gLibVLCMediaPlayer); - libvlc_release(gLibVLC); + libvlc_media_player_stop(mLibVLCMediaPlayer); + libvlc_media_player_release(mLibVLCMediaPlayer); + libvlc_release(mLibVLC); +} + +//////////////////////////////////////////////////////////////////////////////// +// *virtual* +void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + message.setValueReal("current_time", mCurTime); + message.setValueReal("duration", mDuration); + message.setValueReal("current_rate", 1.0f); + + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) +{ + MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr; + if (parent == 0) + { + return; + } + + switch (event->type) + { + case libvlc_MediaPlayerOpening: + parent->setStatus(STATUS_LOADING); + break; + + case libvlc_MediaPlayerBuffering: + parent->setStatus(STATUS_BUFFERING); + break; + + case libvlc_MediaPlayerPlaying: + parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; + parent->setStatus(STATUS_PLAYING); + break; + + case libvlc_MediaPlayerPaused: + parent->setStatus(STATUS_PAUSED); + break; + + case libvlc_MediaPlayerStopped: + parent->setStatus(STATUS_DONE); + break; + + case libvlc_MediaPlayerEndReached: + parent->setStatus(STATUS_DONE); + break; + + case libvlc_MediaPlayerEncounteredError: + parent->setStatus(STATUS_ERROR); + break; + + case libvlc_MediaPlayerTimeChanged: + parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; + break; + + case libvlc_MediaPlayerPositionChanged: + break; + + case libvlc_MediaPlayerLengthChanged: + parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f; + break; + + case libvlc_MediaPlayerTitleChanged: + { + char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title); + if (title) + { + parent->updateTitle(title); + } + } + break; + } } //////////////////////////////////////////////////////////////////////////////// @@ -168,30 +269,73 @@ void MediaPluginLibVLC::playMedia() return; } - if (gLibVLCMediaPlayer) + if (mLibVLCMediaPlayer) + { + // stop listening to events while we reset things + libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); + if (em) + { + libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerBuffering, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL); + libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL); + }; + + libvlc_media_player_stop(mLibVLCMediaPlayer); + libvlc_media_player_release(mLibVLCMediaPlayer); + + mLibVLCMediaPlayer = 0; + } + + if (mLibVLCMedia) { - libvlc_media_player_stop(gLibVLCMediaPlayer); - libvlc_media_player_release(gLibVLCMediaPlayer); + libvlc_media_release(mLibVLCMedia); + + mLibVLCMedia = 0; } - gLibVLCMedia = libvlc_media_new_location(gLibVLC, mURL.c_str()); - if (!gLibVLCMedia) + mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str()); + if (!mLibVLCMedia) { - gLibVLCMediaPlayer = 0; + mLibVLCMediaPlayer = 0; + setStatus(STATUS_ERROR); return; } - gLibVLCMediaPlayer = libvlc_media_player_new_from_media(gLibVLCMedia); - if (!gLibVLCMediaPlayer) + mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia); + if (!mLibVLCMediaPlayer) { + setStatus(STATUS_ERROR); return; } - libvlc_media_release(gLibVLCMedia); + // listen to events + libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer); + if (em) + { + libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerBuffering, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this); + libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this); + } - gVLCCallbackContext.parent = this; - gVLCCallbackContext.texture_pixels = mPixels; - gVLCCallbackContext.mp = gLibVLCMediaPlayer; + mLibVLCCallbackContext.parent = this; + mLibVLCCallbackContext.texture_pixels = mPixels; + mLibVLCCallbackContext.mp = mLibVLCMediaPlayer; // Send a "navigate begin" event. // This is really a browser message but the QuickTime plugin did it and @@ -208,9 +352,24 @@ void MediaPluginLibVLC::playMedia() // it in mCurVolume and set it again here so that volume levels are correctly initialized setVolume(mCurVolume); - libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); - libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); - libvlc_media_player_play(gLibVLCMediaPlayer); + setStatus(STATUS_LOADED); + + libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); + libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); + + if (mIsLooping) + { + libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1"); + } + + libvlc_media_player_play(mLibVLCMediaPlayer); + + // send a "location_changed" message - this informs the media system + // that a new URL is the 'current' one and is used extensively. + // Again, this is really a browser message but we will use it here. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", mURL); + sendMessage(message); // Send a "navigate complete" event. // This is really a browser message but the QuickTime plugin did it and @@ -224,15 +383,24 @@ void MediaPluginLibVLC::playMedia() sendMessage(message_complete); } +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::updateTitle(const char* title) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::setVolume(const F64 volume) { mCurVolume = volume; - if (gLibVLCMediaPlayer) + if (mLibVLCMediaPlayer) { - int result = libvlc_audio_set_volume(gLibVLCMediaPlayer, (int)(volume * 100)); + int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100)); if (result != 0) { // volume wasn't set but not much to be done here @@ -248,26 +416,26 @@ void MediaPluginLibVLC::setVolume(const F64 volume) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginLibVLC::receiveMessage( const char* message_string ) +void MediaPluginLibVLC::receiveMessage(const char* message_string) { - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { initVLC(); - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; - message.setValueLLSD("versions", versions); + message.setValueLLSD("versions", versions); std::ostringstream s; s << "LibVLC plugin "; @@ -277,96 +445,96 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) s << "."; s << LIBVLC_VERSION_REVISION; - message.setValue("plugin_version", s.str()); - sendMessage(message); - } - else if(message_name == "idle") - { - } - else if(message_name == "cleanup") - { + message.setValue("plugin_version", s.str()); + sendMessage(message); + } + else if (message_name == "idle") + { + } + else if (message_name == "cleanup") + { resetVLC(); - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - libvlc_media_player_stop(gLibVLCMediaPlayer); - libvlc_media_player_release(gLibVLCMediaPlayer); - gLibVLCMediaPlayer = 0; - - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + libvlc_media_player_stop(mLibVLCMediaPlayer); + libvlc_media_player_release(mLibVLCMediaPlayer); + mLibVLCMediaPlayer = 0; + + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if (message_name == "init") + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_BGRA_EXT); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", false); - sendMessage(message); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - mTextureWidth = texture_width; - mTextureHeight = texture_height; + message.setValueU32("format", GL_BGRA_EXT); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if (!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + mTextureWidth = texture_width; + mTextureHeight = texture_height; playMedia(); }; - }; + }; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); message.setValue("name", name); @@ -375,74 +543,75 @@ void MediaPluginLibVLC::receiveMessage( const char* message_string ) message.setValueS32("texture_width", texture_width); message.setValueS32("texture_height", texture_height); sendMessage(message); - } - else if(message_name == "load_uri") - { + } + else if (message_name == "load_uri") + { mURL = message_in.getValue("uri"); playMedia(); - } - } - else - if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if (message_name == "stop") + } + } + else + if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { - if (gLibVLCMediaPlayer) + if (message_name == "stop") { - libvlc_media_player_stop(gLibVLCMediaPlayer); + if (mLibVLCMediaPlayer) + { + libvlc_media_player_stop(mLibVLCMediaPlayer); + } } - } - else if (message_name == "start") - { - if (gLibVLCMediaPlayer) + else if (message_name == "start") { - libvlc_media_player_play(gLibVLCMediaPlayer); + if (mLibVLCMediaPlayer) + { + libvlc_media_player_play(mLibVLCMediaPlayer); + } } - } - else if (message_name == "pause") - { - if (gLibVLCMediaPlayer) + else if (message_name == "pause") { - libvlc_media_player_pause(gLibVLCMediaPlayer); + if (mLibVLCMediaPlayer) + { + libvlc_media_player_pause(mLibVLCMediaPlayer); + } + } + else if (message_name == "seek") + { + } + else if (message_name == "set_loop") + { + mIsLooping = true; + } + else if (message_name == "set_volume") + { + // volume comes in 0 -> 1.0 + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); } } - else if (message_name == "seek") - { - } - else if (message_name == "set_loop") - { - } - else if (message_name == "set_volume") - { - // volume comes in 0 -> 1.0 - F64 volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - } + } } //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginLibVLC::init() { - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "LibVLC Plugin" ); - sendMessage( message ); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "LibVLC Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // -int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data ) +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - MediaPluginLibVLC* self = new MediaPluginLibVLC( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; - *plugin_user_data = ( void* )self; + MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data); + *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 08c927483f..9cf3249983 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -911,7 +911,7 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) } x = ll_round((F32)x * LLUI::getScaleFactor().mV[VX]); - if ( coords_opengl ) + if ( ! coords_opengl ) { y = ll_round((F32)(y) * LLUI::getScaleFactor().mV[VY]); } -- cgit v1.2.3 From 84f6b535adc61680e6093db6bae1d17d1733b180 Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Thu, 21 Jul 2016 08:28:14 -0700 Subject: MAINT=6585: fix llleap_test to use llbase not indra.base --- indra/llcommon/tests/llleap_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index d342dece84..71aa885514 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -113,7 +113,7 @@ namespace tut // We expect mydir to be .../indra/llcommon/tests. "sys.path.insert(0,\n" " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" - "from indra.base import llsd\n" + "from llbase import llsd\n" "\n" "class ProtocolError(Exception):\n" " def __init__(self, msg, data):\n" -- cgit v1.2.3 From eb350761f7e0b514f785917dcd9649a4a85db8fc Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Thu, 21 Jul 2016 08:29:45 -0700 Subject: MAINT=6585: remove extraneous path manipulation from llleap_test --- indra/llcommon/tests/llleap_test.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 71aa885514..c387da6c48 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -110,9 +110,6 @@ namespace tut // finding indra/lib/python. Use our __FILE__, with // raw-string syntax to deal with Windows pathnames. "mydir = os.path.dirname(r'" << __FILE__ << "')\n" - // We expect mydir to be .../indra/llcommon/tests. - "sys.path.insert(0,\n" - " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" "from llbase import llsd\n" "\n" "class ProtocolError(Exception):\n" -- cgit v1.2.3 From f0eab8b36ff6ffcb2e76d3e23b0cd35346cb4a3b Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Thu, 21 Jul 2016 09:46:42 -0700 Subject: Add a comment about order of operation that might be important for those that follow --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index f2e8252d3a..948639f125 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -357,6 +357,8 @@ void MediaPluginLibVLC::playMedia() libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); + // note this relies on the "set_loop" message arriving before the "start" (play) one + // but that appears to always be the case if (mIsLooping) { libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1"); -- cgit v1.2.3 From 5ab6b73d57818c7aaf9a4bcd0b302854166fd93a Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Thu, 21 Jul 2016 14:03:19 -0700 Subject: MAINT-6585: redirect elementtree to llbase version --- indra/llcorehttp/tests/test_llcorehttp_peer.py | 4 +--- indra/llmessage/tests/test_llsdmessage_peer.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 5a059e53ca..6c5f37d407 100755 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -42,9 +42,7 @@ except ImportError: from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from SocketServer import ThreadingMixIn -mydir = os.path.dirname(__file__) # expected to be .../indra/llcorehttp/tests/ -sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) -from indra.util.fastest_elementtree import parse as xml_parse +from llbase.fastest_elementtree import parse as xml_parse from llbase import llsd from testrunner import freeport, run, debug, VERBOSE diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 485a125af0..bac18fa374 100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -34,9 +34,7 @@ import sys from threading import Thread from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/ -sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) -from indra.util.fastest_elementtree import parse as xml_parse +from llbase.fastest_elementtree import parse as xml_parse from llbase import llsd from testrunner import freeport, run, debug, VERBOSE import time -- cgit v1.2.3 From befb0446c50cd950315f12d9f545d0e072e8e87b Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Thu, 21 Jul 2016 15:20:00 -0700 Subject: Remove new 'buffering' state for video media - seemed like it'd be useful but it broke things --- indra/media_plugins/base/media_plugin_base.cpp | 1 - indra/media_plugins/base/media_plugin_base.h | 3 +-- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 6 ------ 3 files changed, 1 insertion(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp index a813d5f465..37c498664a 100644 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/media_plugins/base/media_plugin_base.cpp @@ -73,7 +73,6 @@ std::string MediaPluginBase::statusString() case STATUS_PLAYING: result = "playing"; break; case STATUS_PAUSED: result = "paused"; break; case STATUS_DONE: result = "done"; break; - case STATUS_BUFFERING: result = "buffering"; break; default: // keep the empty string break; diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h index 99bc49fc70..38b8226bb3 100644 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/media_plugins/base/media_plugin_base.h @@ -56,8 +56,7 @@ protected: STATUS_ERROR, STATUS_PLAYING, STATUS_PAUSED, - STATUS_DONE, - STATUS_BUFFERING + STATUS_DONE } EStatus; /** Plugin shared memory. */ diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 948639f125..9b5b51f56a 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -212,10 +212,6 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) parent->setStatus(STATUS_LOADING); break; - case libvlc_MediaPlayerBuffering: - parent->setStatus(STATUS_BUFFERING); - break; - case libvlc_MediaPlayerPlaying: parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; parent->setStatus(STATUS_PLAYING); @@ -276,7 +272,6 @@ void MediaPluginLibVLC::playMedia() if (em) { libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL); - libvlc_event_detach(em, libvlc_MediaPlayerBuffering, eventCallbacks, NULL); libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL); libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL); libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL); @@ -321,7 +316,6 @@ void MediaPluginLibVLC::playMedia() if (em) { libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this); - libvlc_event_attach(em, libvlc_MediaPlayerBuffering, eventCallbacks, this); libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this); libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this); libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this); -- cgit v1.2.3 From 609595e9384c86f78f5eb5471c0b7cac4b7fef9e Mon Sep 17 00:00:00 2001 From: Glenn Glazer Date: Thu, 21 Jul 2016 16:51:47 -0700 Subject: MAINT-6585: put back indra/ipc files needed for scripts/template_verifier.py --- indra/lib/python/indra/__init__.py | 25 ++ indra/lib/python/indra/ipc/__init__.py | 27 ++ indra/lib/python/indra/ipc/compatibility.py | 123 +++++++++ indra/lib/python/indra/ipc/llmessage.py | 372 ++++++++++++++++++++++++++++ indra/lib/python/indra/ipc/tokenstream.py | 154 ++++++++++++ 5 files changed, 701 insertions(+) create mode 100755 indra/lib/python/indra/__init__.py create mode 100755 indra/lib/python/indra/ipc/__init__.py create mode 100755 indra/lib/python/indra/ipc/compatibility.py create mode 100755 indra/lib/python/indra/ipc/llmessage.py create mode 100755 indra/lib/python/indra/ipc/tokenstream.py (limited to 'indra') diff --git a/indra/lib/python/indra/__init__.py b/indra/lib/python/indra/__init__.py new file mode 100755 index 0000000000..0c5053cf49 --- /dev/null +++ b/indra/lib/python/indra/__init__.py @@ -0,0 +1,25 @@ +"""\ +@file __init__.py +@brief Initialization file for the indra module. + +$LicenseInfo:firstyear=2006&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2006-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$ +""" diff --git a/indra/lib/python/indra/ipc/__init__.py b/indra/lib/python/indra/ipc/__init__.py new file mode 100755 index 0000000000..302bbf4a03 --- /dev/null +++ b/indra/lib/python/indra/ipc/__init__.py @@ -0,0 +1,27 @@ +"""\ +@file __init__.py +@brief Initialization file for the indra ipc module. + +$LicenseInfo:firstyear=2006&license=mit$ + +Copyright (c) 2006-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" diff --git a/indra/lib/python/indra/ipc/compatibility.py b/indra/lib/python/indra/ipc/compatibility.py new file mode 100755 index 0000000000..b9045c22f3 --- /dev/null +++ b/indra/lib/python/indra/ipc/compatibility.py @@ -0,0 +1,123 @@ +"""\ +@file compatibility.py +@brief Classes that manage compatibility states. + +$LicenseInfo:firstyear=2007&license=mit$ + +Copyright (c) 2007-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" + + +"""Compatibility combination table: + + I M O N S + -- -- -- -- -- +I: I I I I I +M: I M M M M +O: I M O M O +N: I M M N N +S: I M O N S + +""" + +class _Compatibility(object): + def __init__(self, reason): + self.reasons = [ ] + if reason: + self.reasons.append(reason) + + def combine(self, other): + if self._level() <= other._level(): + return self._buildclone(other) + else: + return other._buildclone(self) + + def prefix(self, leadin): + self.reasons = [ leadin + r for r in self.reasons ] + + def same(self): return self._level() >= 1 + def deployable(self): return self._level() > 0 + def resolved(self): return self._level() > -1 + def compatible(self): return self._level() > -2 + + def explain(self): + return self.__class__.__name__ + "\n" + "\n".join(self.reasons) + "\n" + + def _buildclone(self, other=None): + c = self._buildinstance() + c.reasons = self.reasons + if other: + c.reasons = c.reasons + other.reasons + return c + + def _buildinstance(self): + return self.__class__(None) + +# def _level(self): +# raise RuntimeError('implement in subclass') + + +class Incompatible(_Compatibility): + def _level(self): + return -2 + +class Mixed(_Compatibility): + def __init__(self, *inputs): + _Compatibility.__init__(self, None) + for i in inputs: + self.reasons += i.reasons + + def _buildinstance(self): + return self.__class__() + + def _level(self): + return -1 + +class _Aged(_Compatibility): + def combine(self, other): + if self._level() == other._level(): + return self._buildclone(other) + if int(self._level()) == int(other._level()): + return Mixed(self, other) + return _Compatibility.combine(self, other) + +class Older(_Aged): + def _level(self): + return -0.25 + +class Newer(_Aged): + def _level(self): + return 0.25 + +class Same(_Compatibility): + def __init__(self): + _Compatibility.__init__(self, None) + + def _buildinstance(self): + return self.__class__() + + def _level(self): + return 1 + + + + diff --git a/indra/lib/python/indra/ipc/llmessage.py b/indra/lib/python/indra/ipc/llmessage.py new file mode 100755 index 0000000000..91fb36b72c --- /dev/null +++ b/indra/lib/python/indra/ipc/llmessage.py @@ -0,0 +1,372 @@ +"""\ +@file llmessage.py +@brief Message template parsing and compatiblity + +$LicenseInfo:firstyear=2007&license=mit$ + +Copyright (c) 2007-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" + +from compatibility import Incompatible, Older, Newer, Same +from tokenstream import TokenStream + +### +### Message Template +### + +class Template: + def __init__(self): + self.messages = { } + + def addMessage(self, m): + self.messages[m.name] = m + + def compatibleWithBase(self, base): + messagenames = ( + frozenset(self.messages.keys()) + | frozenset(base.messages.keys()) + ) + + compatibility = Same() + for name in messagenames: + selfmessage = self.messages.get(name, None) + basemessage = base.messages.get(name, None) + + if not selfmessage: + c = Older("missing message %s, did you mean to deprecate?" % name) + elif not basemessage: + c = Newer("added message %s" % name) + else: + c = selfmessage.compatibleWithBase(basemessage) + c.prefix("in message %s: " % name) + + compatibility = compatibility.combine(c) + + return compatibility + + + +class Message: + HIGH = "High" + MEDIUM = "Medium" + LOW = "Low" + FIXED = "Fixed" + priorities = [ HIGH, MEDIUM, LOW, FIXED ] + prioritieswithnumber = [ FIXED ] + + TRUSTED = "Trusted" + NOTTRUSTED = "NotTrusted" + trusts = [ TRUSTED, NOTTRUSTED ] + + UNENCODED = "Unencoded" + ZEROCODED = "Zerocoded" + encodings = [ UNENCODED, ZEROCODED ] + + NOTDEPRECATED = "NotDeprecated" + DEPRECATED = "Deprecated" + UDPDEPRECATED = "UDPDeprecated" + UDPBLACKLISTED = "UDPBlackListed" + deprecations = [ NOTDEPRECATED, UDPDEPRECATED, UDPBLACKLISTED, DEPRECATED ] + # in order of increasing deprecation + + def __init__(self, name, number, priority, trust, coding): + self.name = name + self.number = number + self.priority = priority + self.trust = trust + self.coding = coding + self.deprecateLevel = 0 + self.blocks = [ ] + + def deprecated(self): + return self.deprecateLevel != 0 + + def deprecate(self, deprecation): + self.deprecateLevel = self.deprecations.index(deprecation) + + def addBlock(self, block): + self.blocks.append(block) + + def compatibleWithBase(self, base): + if self.name != base.name: + # this should never happen in real life because of the + # way Template matches up messages by name + return Incompatible("has different name: %s vs. %s in base" + % (self.name, base.name)) + if self.priority != base.priority: + return Incompatible("has different priority: %s vs. %s in base" + % (self.priority, base.priority)) + if self.trust != base.trust: + return Incompatible("has different trust: %s vs. %s in base" + % (self.trust, base.trust)) + if self.coding != base.coding: + return Incompatible("has different coding: %s vs. %s in base" + % (self.coding, base.coding)) + if self.number != base.number: + return Incompatible("has different number: %s vs. %s in base" + % (self.number, base.number)) + + compatibility = Same() + + if self.deprecateLevel != base.deprecateLevel: + if self.deprecateLevel < base.deprecateLevel: + c = Older("is less deprecated: %s vs. %s in base" % ( + self.deprecations[self.deprecateLevel], + self.deprecations[base.deprecateLevel])) + else: + c = Newer("is more deprecated: %s vs. %s in base" % ( + self.deprecations[self.deprecateLevel], + self.deprecations[base.deprecateLevel])) + compatibility = compatibility.combine(c) + + selflen = len(self.blocks) + baselen = len(base.blocks) + samelen = min(selflen, baselen) + + for i in xrange(0, samelen): + selfblock = self.blocks[i] + baseblock = base.blocks[i] + + c = selfblock.compatibleWithBase(baseblock) + if not c.same(): + c = Incompatible("block %d isn't identical" % i) + compatibility = compatibility.combine(c) + + if selflen > baselen: + c = Newer("has %d extra blocks" % (selflen - baselen)) + elif selflen < baselen: + c = Older("missing %d extra blocks" % (baselen - selflen)) + else: + c = Same() + + compatibility = compatibility.combine(c) + return compatibility + + + +class Block(object): + SINGLE = "Single" + MULTIPLE = "Multiple" + VARIABLE = "Variable" + repeats = [ SINGLE, MULTIPLE, VARIABLE ] + repeatswithcount = [ MULTIPLE ] + + def __init__(self, name, repeat, count=None): + self.name = name + self.repeat = repeat + self.count = count + self.variables = [ ] + + def addVariable(self, variable): + self.variables.append(variable) + + def compatibleWithBase(self, base): + if self.name != base.name: + return Incompatible("has different name: %s vs. %s in base" + % (self.name, base.name)) + if self.repeat != base.repeat: + return Incompatible("has different repeat: %s vs. %s in base" + % (self.repeat, base.repeat)) + if self.repeat in Block.repeatswithcount: + if self.count != base.count: + return Incompatible("has different count: %s vs. %s in base" + % (self.count, base.count)) + + compatibility = Same() + + selflen = len(self.variables) + baselen = len(base.variables) + + for i in xrange(0, min(selflen, baselen)): + selfvar = self.variables[i] + basevar = base.variables[i] + + c = selfvar.compatibleWithBase(basevar) + if not c.same(): + c = Incompatible("variable %d isn't identical" % i) + compatibility = compatibility.combine(c) + + if selflen > baselen: + c = Newer("has %d extra variables" % (selflen - baselen)) + elif selflen < baselen: + c = Older("missing %d extra variables" % (baselen - selflen)) + else: + c = Same() + + compatibility = compatibility.combine(c) + return compatibility + + + +class Variable: + U8 = "U8"; U16 = "U16"; U32 = "U32"; U64 = "U64" + S8 = "S8"; S16 = "S16"; S32 = "S32"; S64 = "S64" + F32 = "F32"; F64 = "F64" + LLVECTOR3 = "LLVector3"; LLVECTOR3D = "LLVector3d"; LLVECTOR4 = "LLVector4" + LLQUATERNION = "LLQuaternion" + LLUUID = "LLUUID" + BOOL = "BOOL" + IPADDR = "IPADDR"; IPPORT = "IPPORT" + FIXED = "Fixed" + VARIABLE = "Variable" + types = [ U8, U16, U32, U64, S8, S16, S32, S64, F32, F64, + LLVECTOR3, LLVECTOR3D, LLVECTOR4, LLQUATERNION, + LLUUID, BOOL, IPADDR, IPPORT, FIXED, VARIABLE ] + typeswithsize = [ FIXED, VARIABLE ] + + def __init__(self, name, type, size): + self.name = name + self.type = type + self.size = size + + def compatibleWithBase(self, base): + if self.name != base.name: + return Incompatible("has different name: %s vs. %s in base" + % (self.name, base.name)) + if self.type != base.type: + return Incompatible("has different type: %s vs. %s in base" + % (self.type, base.type)) + if self.type in Variable.typeswithsize: + if self.size != base.size: + return Incompatible("has different size: %s vs. %s in base" + % (self.size, base.size)) + return Same() + + + +### +### Parsing Message Templates +### + +class TemplateParser: + def __init__(self, tokens): + self._tokens = tokens + self._version = 0 + self._numbers = { } + for p in Message.priorities: + self._numbers[p] = 0 + + def parseTemplate(self): + tokens = self._tokens + t = Template() + while True: + if tokens.want("version"): + v = float(tokens.require(tokens.wantFloat())) + self._version = v + t.version = v + continue + + m = self.parseMessage() + if m: + t.addMessage(m) + continue + + if self._version >= 2.0: + tokens.require(tokens.wantEOF()) + break + else: + if tokens.wantEOF(): + break + + tokens.consume() + # just assume (gulp) that this is a comment + # line 468: "sim -> dataserver" + return t + + + def parseMessage(self): + tokens = self._tokens + if not tokens.want("{"): + return None + + name = tokens.require(tokens.wantSymbol()) + priority = tokens.require(tokens.wantOneOf(Message.priorities)) + + if self._version >= 2.0 or priority in Message.prioritieswithnumber: + number = int("+" + tokens.require(tokens.wantInteger()), 0) + else: + self._numbers[priority] += 1 + number = self._numbers[priority] + + trust = tokens.require(tokens.wantOneOf(Message.trusts)) + coding = tokens.require(tokens.wantOneOf(Message.encodings)) + + m = Message(name, number, priority, trust, coding) + + if self._version >= 2.0: + d = tokens.wantOneOf(Message.deprecations) + if d: + m.deprecate(d) + + while True: + b = self.parseBlock() + if not b: + break + m.addBlock(b) + + tokens.require(tokens.want("}")) + + return m + + + def parseBlock(self): + tokens = self._tokens + if not tokens.want("{"): + return None + name = tokens.require(tokens.wantSymbol()) + repeat = tokens.require(tokens.wantOneOf(Block.repeats)) + if repeat in Block.repeatswithcount: + count = int(tokens.require(tokens.wantInteger())) + else: + count = None + + b = Block(name, repeat, count) + + while True: + v = self.parseVariable() + if not v: + break + b.addVariable(v) + + tokens.require(tokens.want("}")) + return b + + + def parseVariable(self): + tokens = self._tokens + if not tokens.want("{"): + return None + name = tokens.require(tokens.wantSymbol()) + type = tokens.require(tokens.wantOneOf(Variable.types)) + if type in Variable.typeswithsize: + size = tokens.require(tokens.wantInteger()) + else: + tokens.wantInteger() # in LandStatRequest: "{ ParcelLocalID S32 1 }" + size = None + tokens.require(tokens.want("}")) + return Variable(name, type, size) + +def parseTemplateString(s): + return TemplateParser(TokenStream().fromString(s)).parseTemplate() + +def parseTemplateFile(f): + return TemplateParser(TokenStream().fromFile(f)).parseTemplate() diff --git a/indra/lib/python/indra/ipc/tokenstream.py b/indra/lib/python/indra/ipc/tokenstream.py new file mode 100755 index 0000000000..b96f26d3ff --- /dev/null +++ b/indra/lib/python/indra/ipc/tokenstream.py @@ -0,0 +1,154 @@ +"""\ +@file tokenstream.py +@brief Message template parsing utility class + +$LicenseInfo:firstyear=2007&license=mit$ + +Copyright (c) 2007-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" + +import re + +class _EOF(object): + pass + +EOF = _EOF() + +class _LineMarker(int): + pass + +_commentRE = re.compile(r'//.*') +_symbolRE = re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*') +_integerRE = re.compile(r'(0x[0-9A-Fa-f]+|0\d*|[1-9]\d*)') +_floatRE = re.compile(r'\d+(\.\d*)?') + + +class ParseError(Exception): + def __init__(self, stream, reason): + self.line = stream.line + self.context = stream._context() + self.reason = reason + + def _contextString(self): + c = [ ] + for t in self.context: + if isinstance(t, _LineMarker): + break + c.append(t) + return " ".join(c) + + def __str__(self): + return "line %d: %s @ ... %s" % ( + self.line, self.reason, self._contextString()) + + def __nonzero__(self): + return False + + +def _optionText(options): + n = len(options) + if n == 1: + return '"%s"' % options[0] + return '"' + '", "'.join(options[0:(n-1)]) + '" or "' + options[-1] + '"' + + +class TokenStream(object): + def __init__(self): + self.line = 0 + self.tokens = [ ] + + def fromString(self, string): + return self.fromLines(string.split('\n')) + + def fromFile(self, file): + return self.fromLines(file) + + def fromLines(self, lines): + i = 0 + for line in lines: + i += 1 + self.tokens.append(_LineMarker(i)) + self.tokens.extend(_commentRE.sub(" ", line).split()) + self._consumeLines() + return self + + def consume(self): + if not self.tokens: + return EOF + t = self.tokens.pop(0) + self._consumeLines() + return t + + def _consumeLines(self): + while self.tokens and isinstance(self.tokens[0], _LineMarker): + self.line = self.tokens.pop(0) + + def peek(self): + if not self.tokens: + return EOF + return self.tokens[0] + + def want(self, t): + if t == self.peek(): + return self.consume() + return ParseError(self, 'expected "%s"' % t) + + def wantOneOf(self, options): + assert len(options) + if self.peek() in options: + return self.consume() + return ParseError(self, 'expected one of %s' % _optionText(options)) + + def wantEOF(self): + return self.want(EOF) + + def wantRE(self, re, message=None): + t = self.peek() + if t != EOF: + m = re.match(t) + if m and m.end() == len(t): + return self.consume() + if not message: + message = "expected match for r'%s'" % re.pattern + return ParseError(self, message) + + def wantSymbol(self): + return self.wantRE(_symbolRE, "expected symbol") + + def wantInteger(self): + return self.wantRE(_integerRE, "expected integer") + + def wantFloat(self): + return self.wantRE(_floatRE, "expected float") + + def _context(self): + n = min(5, len(self.tokens)) + return self.tokens[0:n] + + def require(self, t): + if t: + return t + if isinstance(t, ParseError): + raise t + else: + raise ParseError(self, "unmet requirement") + -- cgit v1.2.3 From 8cd9569cefdd7877859e87a67dd93d1962328e6d Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Thu, 21 Jul 2016 21:06:06 -0700 Subject: First pass at enabling time based media (videos) scrubbing controls --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 5 +++ indra/newview/llpanelprimmediacontrols.cpp | 46 ++++++++++++++-------- indra/newview/llpanelprimmediacontrols.h | 8 +++- .../default/xui/en/panel_prim_media_controls.xml | 8 ++-- 4 files changed, 46 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 9b5b51f56a..c1e34b5c8f 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -572,6 +572,11 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) } else if (message_name == "seek") { + if (mDuration > 0) + { + F64 normalized_offset = message_in.getValueReal("time") / mDuration; + libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset); + } } else if (message_name == "set_loop") { diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 763657ebad..0bcd8a9e63 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mVolumeSliderVisible(0), mWindowShade(NULL), mHideImmediately(false), - mSecureURL(false) + mSecureURL(false), + mMediaPlaySliderCtrlMouseDownValue(0.0) { mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this)); mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this)); mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this)); - mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this)); + mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this)); + mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this)); mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this)); @@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL() #endif // USE_COMBO_BOX_FOR_MEDIA_URL } -void LLPanelPrimMediaControls::onCommitSlider() + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown() { - focusOnTarget(); + mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal(); - LLViewerMediaImpl* media_impl = getTargetMediaImpl(); - if (media_impl) + mUpdateSlider = false; +} + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp() +{ + F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal(); + + if (mMediaPlaySliderCtrlMouseDownValue != cur_value) { - // get slider value - F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal(); - if(slider_value <= 0.0) - { - media_impl->stop(); - } - else + focusOnTarget(); + + LLViewerMediaImpl* media_impl = getTargetMediaImpl(); + if (media_impl) { - media_impl->seek(slider_value*mMovieDuration); - //mUpdateSlider= false; + if (cur_value <= 0.0) + { + media_impl->stop(); + } + else + { + media_impl->seek(cur_value * mMovieDuration); + } } + + mUpdateSlider = true; } -} +} void LLPanelPrimMediaControls::onCommitVolumeUp() { diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 6d2eb3430e..21d5236074 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -107,8 +107,10 @@ private: void updateZoom(); void setCurrentURL(); - void onCommitSlider(); - + + void onMediaPlaySliderCtrlMouseDown(); + void onMediaPlaySliderCtrlMouseUp(); + void onCommitVolumeUp(); void onCommitVolumeDown(); void onCommitVolumeSlider(); @@ -219,6 +221,8 @@ private: S32 mVolumeSliderVisible; LLNotificationPtr mActiveNotification; + + F64 mMediaPlaySliderCtrlMouseDownValue; }; #endif // LL_PANELPRIMMEDIACONTROLS_H diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index eb67d07601..068e4420bc 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -374,9 +374,11 @@ layout="topleft" tool_tip="Movie play progress" width="200"> - - + + + Date: Fri, 22 Jul 2016 13:56:26 -0700 Subject: More Y flip madness - 2D media on OS X is has flipped Y mouse coords but correct on 3D/MOAP - reluctantly adding per platform switch --- indra/newview/llmediactrl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 9cf3249983..5fed925dda 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -907,7 +907,14 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) if(mMediaSource && mMediaSource->hasMedia()) { +// on OS X (maybe Linux) and on 2D media like login/search, the coords are wrong. +// they are fine on 3D media - so we flip (or is it unflip) them here for anything +// except windows (Which appears to be correct on both counts) +#if LL_WINDOWS coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); +#else + coords_opengl = ! mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); +#endif } x = ll_round((F32)x * LLUI::getScaleFactor().mV[VX]); -- cgit v1.2.3 From 6f09cf76cd79108fcdc213f1f945540f08442c5d Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Fri, 22 Jul 2016 16:27:53 -0700 Subject: Polish web content floater - rename to reflect it now does all media. remove developer options when Develop menu closed. start at google home page by default. --- indra/newview/llfloaterwebcontent.cpp | 22 ++--- indra/newview/llfloaterwebcontent.h | 3 +- .../skins/default/xui/en/floater_web_content.xml | 108 +++++++++++++-------- indra/newview/skins/default/xui/en/menu_login.xml | 6 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 25 +---- 5 files changed, 84 insertions(+), 80 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index c039b3b8f4..adb3322759 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -82,7 +82,7 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params ) mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this)); - mCommitCallbackRegistrar.add( "WebContent.TestVideo", boost::bind(&LLFloaterWebContent::onTestVideo, this, _2)); + mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2)); } BOOL LLFloaterWebContent::postBuild() @@ -111,6 +111,9 @@ BOOL LLFloaterWebContent::postBuild() // initialize the URL history using the system URL History manager initializeURLHistory(); + // if "Develop" Menu open, sety a flag and change things to be more useful for devs + mDevelopMode = gSavedSettings.getBOOL("QAMode"); + return TRUE; } @@ -196,8 +199,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) width + getRect().getWidth() - browser_rect.getWidth(), height + getRect().getHeight() - browser_rect.getHeight()); - LL_DEBUGS() << "geometry change: " << geom << LL_ENDL; - LLRect new_rect; getParent()->screenRectToLocal(geom, &new_rect); setShape(new_rect); @@ -206,8 +207,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) // static void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) { - LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL; - if (!p.id.isProvided()) { p.id = LLUUID::generateNewID().asString(); @@ -225,12 +224,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) // and close the least recently opened one if this will put us over the limit. LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class); - LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL; - - for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) - { - LL_DEBUGS() << " " << (*iter)->getKey()["target"] << LL_ENDL; - } if(instances.size() >= (size_t)browser_window_limit) { @@ -242,7 +235,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) void LLFloaterWebContent::open_media(const Params& p) { - // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); mWebBrowser->setHomePageUrl(p.url); mWebBrowser->setTarget(p.target); @@ -252,6 +244,10 @@ void LLFloaterWebContent::open_media(const Params& p) getChild("status_bar")->setVisible(p.show_chrome); getChild("nav_controls")->setVisible(p.show_chrome); + + // turn additional debug controls on but only for Develop mode (Develop menu open) + getChild("debug_controls")->setVisible(mDevelopMode); + bool address_entry_enabled = p.allow_address_entry && !p.trusted_content; mAllowNavigation = p.allow_back_forward_navigation; getChildView("address")->setEnabled(address_entry_enabled); @@ -516,7 +512,7 @@ void LLFloaterWebContent::onPopExternal() }; } -void LLFloaterWebContent::onTestVideo(std::string url) +void LLFloaterWebContent::onTestURL(std::string url) { LLStringUtil::trim(url); if (url.length() > 0) diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 519b575b38..1157d0aab8 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -92,7 +92,7 @@ protected: void onClickStop(); void onEnterAddress(); void onPopExternal(); - void onTestVideo(std::string url); + void onTestURL(std::string url); static void preCreate(Params& p); void open_media(const Params& ); @@ -114,6 +114,7 @@ protected: std::string mUUID; bool mShowPageTitle; bool mAllowNavigation; + bool mDevelopMode; }; #endif // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 7b63a67415..4473ce0cda 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -25,10 +25,10 @@ @@ -152,112 +152,136 @@ + + + - - - - - + label="Media Browser" + name="Media Browser"> + parameter="http://google.com"/> - - - - + label="Media Browser" + name="Media Browser" + shortcut="control|alt|shift|Z"> + parameter="http://google.com"/> Date: Tue, 26 Jul 2016 11:31:37 +0300 Subject: MAINT-6566 Avatar sliders display incorrect values immediately after saving a copy of the wearable. --- indra/newview/llagentwearables.cpp | 3 ++- indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/llviewerwearable.cpp | 6 +++--- indra/newview/llviewerwearable.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 718c1c2251..060bb4c6b9 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -262,6 +262,7 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i { LLAppearanceMgr::instance().addCOFItemLink(inv_item, new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription); + editWearable(inv_item); } } @@ -432,7 +433,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, // old_wearable may still be referred to by other inventory items. Revert // unsaved changes so other inventory items aren't affected by the changes // that were just saved. - old_wearable->revertValues(); + old_wearable->revertValues(false); } void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 86135ee6e8..f07f0ed86c 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -383,7 +383,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { - if (!mEditWearable || mEditWearable->getVisible() == visible) + if (!mEditWearable || ((mEditWearable->getWearable() == wearable) && mEditWearable->getVisible() == visible)) { // visibility isn't changing, hence nothing to do return; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 0f73515b5d..1fa8884b9d 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -451,7 +451,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) - revertValues(); + revertValues(false); } void LLViewerWearable::setItemID(const LLUUID& item_id) @@ -459,13 +459,13 @@ void LLViewerWearable::setItemID(const LLUUID& item_id) mItemID = item_id; } -void LLViewerWearable::revertValues() +void LLViewerWearable::revertValues(bool update_panel) { LLWearable::revertValues(); LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel ) + if( panel && update_panel) { panel->updateScrollingPanelList(); } diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 62cd5e21ad..6f116d3226 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -82,7 +82,7 @@ public: friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w); - /*virtual*/ void revertValues(); + /*virtual*/ void revertValues(bool update_panel = true); /*virtual*/ void saveValues(); // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). -- cgit v1.2.3 From 51935673458479fccf6e2857a3ab5aeffaf11d23 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 26 Jul 2016 11:42:54 +0300 Subject: MAINT-6592 Duplicate entries are shown in Object list in Script info floater after clicking "Return" button --- indra/newview/llfloaterscriptlimits.cpp | 10 ++++++++++ indra/newview/llfloaterscriptlimits.h | 1 + 2 files changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 7b8fc5b35b..eae16b9f03 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -660,6 +660,8 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild() { return FALSE; } + list->setCommitCallback(boost::bind(&LLPanelScriptLimitsRegionMemory::checkButtonsEnabled, this)); + checkButtonsEnabled(); //set all columns to resizable mode even if some columns will be empty for(S32 column = 0; column < list->getNumColumns(); column++) @@ -750,6 +752,14 @@ void LLPanelScriptLimitsRegionMemory::clearList() getChild("parcels_listed")->setValue(LLSD(msg_empty_string)); mObjectListItems.clear(); + checkButtonsEnabled(); +} + +void LLPanelScriptLimitsRegionMemory::checkButtonsEnabled() +{ + LLScrollListCtrl* list = getChild("scripts_list"); + getChild("highlight_btn")->setEnabled(list->getNumSelected() > 0); + getChild("return_btn")->setEnabled(list->getNumSelected() > 0); } // static diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index e3cbbd185f..2ac3862b4f 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -113,6 +113,7 @@ public: void showBeacon(); void returnObjectsFromParcel(S32 local_id); void returnObjects(); + void checkButtonsEnabled(); private: void onNameCache(const LLUUID& id, -- cgit v1.2.3 From f0ab36aec55550ed86d969ccdbad45c5a8db277c Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 26 Jul 2016 16:12:53 +0300 Subject: build fix --- indra/newview/llagentwearables.cpp | 2 +- indra/newview/llviewerwearable.cpp | 11 ++++++++--- indra/newview/llviewerwearable.h | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 060bb4c6b9..170e4063a1 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -433,7 +433,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, // old_wearable may still be referred to by other inventory items. Revert // unsaved changes so other inventory items aren't affected by the changes // that were just saved. - old_wearable->revertValues(false); + old_wearable->revertValuesWithoutUpdate(); } void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 1fa8884b9d..88eb13e7cd 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -451,7 +451,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) - revertValues(false); + revertValuesWithoutUpdate(); } void LLViewerWearable::setItemID(const LLUUID& item_id) @@ -459,18 +459,23 @@ void LLViewerWearable::setItemID(const LLUUID& item_id) mItemID = item_id; } -void LLViewerWearable::revertValues(bool update_panel) +void LLViewerWearable::revertValues() { LLWearable::revertValues(); LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel && update_panel) + if( panel ) { panel->updateScrollingPanelList(); } } +void LLViewerWearable::revertValuesWithoutUpdate() +{ + LLWearable::revertValues(); +} + void LLViewerWearable::saveValues() { LLWearable::saveValues(); diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 6f116d3226..cc99f6af2f 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -82,9 +82,11 @@ public: friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w); - /*virtual*/ void revertValues(bool update_panel = true); + /*virtual*/ void revertValues(); /*virtual*/ void saveValues(); + void revertValuesWithoutUpdate(); + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). /*virtual*/void setUpdated() const; -- cgit v1.2.3 From 9c6eb9ae4088b355d01ada204879b973aa160b7c Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 25 Jul 2016 18:18:53 +0300 Subject: MAINT-4146 - [Griefing] Folders from muted avatars not sent to trash at login --- indra/newview/llinventorymodel.cpp | 4 ++-- indra/newview/llviewermessage.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index d328973bae..5230e8dff9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1050,7 +1050,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 if(old_cat) { // We already have an old category, modify its values - U32 mask = LLInventoryObserver::NONE; LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) @@ -1105,7 +1104,8 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 item_array_t* itemsp = new item_array_t; mParentChildCategoryTree[new_cat->getUUID()] = catsp; mParentChildItemTree[new_cat->getUUID()] = itemsp; - addChangedMask(LLInventoryObserver::ADD, cat->getUUID()); + mask |= LLInventoryObserver::ADD; + addChangedMask(mask, cat->getUUID()); } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5495c0e06a..3925154c0f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1639,7 +1639,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); discard_agent_offer->startFetch(); - if (catp || (itemp && itemp->isFinished())) + if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished())) { discard_agent_offer->done(); } -- cgit v1.2.3 From 19640c015ecfefde767be49168684b27f5ceabb2 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 25 Jul 2016 12:09:55 -0700 Subject: Remove unncessary Y flip --- indra/newview/llmediactrl.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 5fed925dda..9cf3249983 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -907,14 +907,7 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) if(mMediaSource && mMediaSource->hasMedia()) { -// on OS X (maybe Linux) and on 2D media like login/search, the coords are wrong. -// they are fine on 3D media - so we flip (or is it unflip) them here for anything -// except windows (Which appears to be correct on both counts) -#if LL_WINDOWS coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); -#else - coords_opengl = ! mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); -#endif } x = ll_round((F32)x * LLUI::getScaleFactor().mV[VX]); -- cgit v1.2.3 From 5e2676994cf1816ff1a39eb69d90662b5087d367 Mon Sep 17 00:00:00 2001 From: Ansariel Hiller Date: Tue, 26 Jul 2016 19:26:28 +0000 Subject: Fix HttpCoroutineAdapter name for clarity --- indra/llmessage/message.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index cecb2021e7..290b67feb3 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -4007,7 +4007,7 @@ void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::st { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy)); + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); -- cgit v1.2.3 From 781cf7fac47812d8f779113e61fa02daa97b67fe Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 27 Jul 2016 09:53:20 -0400 Subject: remove use of "override" C++11 feature not supported on gcc 4.6 --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index c1e34b5c8f..0bd323eb58 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -61,7 +61,7 @@ private: static void unlock(void* data, void* id, void* const* raw_pixels); static void display(void* data, void* id); - /*virtual*/ void setDirty(int left, int top, int right, int bottom) override; + /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */; static void eventCallbacks(const libvlc_event_t* event, void* ptr); -- cgit v1.2.3 From c32b27f5b77c7d8e53b11163d04f2842949d71de Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 27 Jul 2016 11:19:50 -0400 Subject: increment version number to 4.1.1 --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 43beb4001b..627a3f43a6 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -4.0.7 +4.1.1 -- cgit v1.2.3 From c64bf21131cfedfce3f4519185ae1733ebada4d9 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 28 Jul 2016 11:54:32 +0300 Subject: MAINT-6598 replace all instances of "jelly doll" with JellyDoll in the viewer ui --- .../skins/default/xui/en/floater_preferences_graphics_advanced.xml | 2 +- indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 2bd3aa8bcc..c6b91a8b2f 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -117,7 +117,7 @@ Date: Wed, 27 Jul 2016 20:33:04 +0300 Subject: MAINT-612 FIXED LOD switch distance calculation ignores z-axis scale --- indra/llmath/llvolume.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index d932eb53a0..567ad9a414 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2143,19 +2143,22 @@ BOOL LLVolume::generate() F32 profile_detail = mDetail; F32 path_detail = mDetail; - - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { + //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } } - + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); -- cgit v1.2.3 From bcadc2c1b35d458d0a90293f77778f4313f47ba4 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 29 Jul 2016 17:53:33 +0300 Subject: MAINT-1660 Don't hide script editor floater immediately after removing script from inventory. --- indra/newview/llinventorybridge.cpp | 6 ++++-- indra/newview/llinventorymodel.cpp | 6 +++++- indra/newview/llpreviewscript.cpp | 18 +++++++++++++++--- indra/newview/llpreviewscript.h | 4 ++++ indra/newview/skins/default/xui/en/strings.xml | 3 ++- 5 files changed, 30 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f4bf38f65d..8d130c08e5 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1933,13 +1933,15 @@ BOOL LLItemBridge::removeItem() } // move it to the trash - LLPreview::hide(mUUID, TRUE); LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); LLViewerInventoryItem* item = getItem(); if (!item) return FALSE; - + if (item->getType() != LLAssetType::AT_LSL_TEXT) + { + LLPreview::hide(mUUID, TRUE); + } // Already in trash if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5230e8dff9..503fa28a33 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1395,7 +1395,11 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f } // From purgeObject() - LLPreview::hide(object_id); + LLViewerInventoryItem *item = getItem(object_id); + if (item && (item->getType() != LLAssetType::AT_LSL_TEXT)) + { + LLPreview::hide(object_id, TRUE); + } deleteObject(object_id, fix_broken_links, do_notify_observers); } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 5b1b356597..f28ffce602 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -375,7 +375,8 @@ LLScriptEdCore::LLScriptEdCore( mLiveFile(NULL), mLive(live), mContainer(container), - mHasScriptData(FALSE) + mHasScriptData(FALSE), + mScriptRemoved(FALSE) { setFollowsAll(); setBorderVisible(FALSE); @@ -666,7 +667,7 @@ bool LLScriptEdCore::hasChanged() void LLScriptEdCore::draw() { BOOL script_changed = hasChanged(); - getChildView("Save_btn")->setEnabled(script_changed); + getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved); if( mEditor->hasFocus() ) { @@ -840,7 +841,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) BOOL LLScriptEdCore::canClose() { - if(mForceClose || !hasChanged()) + if(mForceClose || !hasChanged() || mScriptRemoved) { return TRUE; } @@ -1511,6 +1512,17 @@ BOOL LLPreviewLSL::postBuild() return LLPreview::postBuild(); } +void LLPreviewLSL::draw() +{ + const LLInventoryItem* item = getItem(); + if(!item) + { + setTitle(LLTrans::getString("ScriptWasDeleted")); + mScriptEd->setItemRemoved(TRUE); + } + + LLPreview::draw(); +} // virtual void LLPreviewLSL::callbackLSLCompileSucceeded() { diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index a8c6a6eeeb..6b31125641 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -119,6 +119,8 @@ public: void setScriptName(const std::string& name){mScriptName = name;}; + void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;}; + private: void onBtnHelp(); void onBtnDynamicHelp(); @@ -163,6 +165,7 @@ private: BOOL mHasScriptData; LLLiveLSLFile* mLiveFile; LLUUID mAssociatedExperience; + BOOL mScriptRemoved; LLScriptEdContainer* mContainer; // parent view @@ -198,6 +201,7 @@ public: /*virtual*/ BOOL postBuild(); protected: + virtual void draw(); virtual BOOL canClose(); void closeIfNeeded(); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b19c6756bc..ac92e6fa9f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2566,7 +2566,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f Save complete. File upload failed: Script (object out of range) - + Script (deleted from inventory) + Object [OBJECT] owned by [OWNER] -- cgit v1.2.3 From 22e69897db61a62794116eb81e8b413ac180b8e7 Mon Sep 17 00:00:00 2001 From: AndreyL ProductEngine Date: Tue, 2 Aug 2016 06:22:43 +0300 Subject: MAINT-6605 Fix for the crash in LLClipboard::addToClipboard() - Added the exception handling --- indra/llui/llclipboard.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp index 1d18cb2bb0..06fac190ed 100644 --- a/indra/llui/llclipboard.cpp +++ b/indra/llui/llclipboard.cpp @@ -123,7 +123,15 @@ bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool u // Concatenate the input string to the LL and the system clipboard bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) { - mString = src.substr(pos, len); + try + { + mString = src.substr(pos, len); + } + catch (const std::exception& e) + { + LL_WARNS() << "Can't add the substring to clipboard: " << e.what() << LL_ENDL; + return false; + } return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString)); } -- cgit v1.2.3 From 22238182c67b3d322e82bb042ad1d618c733a36d Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 2 Aug 2016 21:28:26 +0300 Subject: MAINT-6259 Rigged mesh LOD swapping --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llvovolume.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c3d7d67c86..f1d0901a81 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10227,7 +10227,7 @@ Type F32 Value - 7.5 + 6.5 RenderWater diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 5fc571bf1d..1112b7dee6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1257,7 +1257,18 @@ BOOL LLVOVolume::calcLOD() lod_factor *= LLVOVolume::sRiggedFactorMultiplier; distance = avatar->mDrawable->mDistanceWRTCamera; F32 avatar_radius = avatar->getBinRadius(); - F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + F32 object_radius; + if (mDrawable.notNull() && !mDrawable->isDead()) + { + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a diff; + diff.setSub(ext[1], ext[0]); + object_radius = diff.getLength3().getF32(); + } + else + { + object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + } radius = object_radius * LLVOVolume::sRiggedFactorMultiplier; radius = llmin(radius, avatar_radius); } -- cgit v1.2.3 From 6c56c9bf6763e22442cdc16706f0fb978a0ec46d Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 9 Aug 2016 15:38:16 +0300 Subject: MAINT-6620 FIXED Use internal or external browser according to Preferences --- indra/newview/llfloaterbuycurrency.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index e21a8594bc..91436e52fe 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -280,7 +280,7 @@ void LLFloaterBuyCurrencyUI::onClickCancel() void LLFloaterBuyCurrencyUI::onClickErrorWeb() { - LLWeb::loadURLExternal(mManager.errorURI()); + LLWeb::loadURL(mManager.errorURI()); closeFloater(); // Update L$ balance LLStatusBar::sendMoneyBalanceRequest(); -- cgit v1.2.3 From f4f30dae0f173517fa1cd58cead142d60cbcc839 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 8 Aug 2016 21:31:11 +0300 Subject: MAINT-6612 Server release notes in Help -> About Second Life never fetch on any region. --- indra/newview/llfloaterabout.cpp | 74 +++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index bababca652..8d17f4c198 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -108,6 +108,7 @@ private: static const std::string sCheckUpdateListenerName; static void startFetchServerReleaseNotes(); + static void fetchServerReleaseNotesCoro(const std::string& cap_url); static void handleServerReleaseNotes(LLSD results); }; @@ -224,35 +225,62 @@ void LLFloaterAbout::startFetchServerReleaseNotes() // an URL suitable for external browsers in the "Location:" HTTP header. std::string cap_url = region->getCapability("ServerReleaseNotes"); - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url, - &LLFloaterAbout::handleServerReleaseNotes, &LLFloaterAbout::handleServerReleaseNotes); + LLCoros::instance().launch("fetchServerReleaseNotesCoro", boost::bind(&LLFloaterAbout::fetchServerReleaseNotesCoro, cap_url)); } +/*static*/ +void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url) +{ + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("fetchServerReleaseNotesCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + httpOpts->setWantHeaders(true); + httpOpts->setFollowRedirects(false); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + handleServerReleaseNotes(httpResults); + } + else + { + handleServerReleaseNotes(result); + } +} + /*static*/ void LLFloaterAbout::handleServerReleaseNotes(LLSD results) { -// LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance("sl_about"); -// if (floater_about) -// { - LLSD http_headers; - if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS)) - { - LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; - } - else - { - http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; - } - - std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString(); - if (location.empty()) - { - location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); - } - LLAppViewer::instance()->setServerReleaseNotesURL(location); -// } + LLSD http_headers; + if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS)) + { + LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + } + else + { + http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + } + + std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString(); + if (location.empty()) + { + location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); + } + LLAppViewer::instance()->setServerReleaseNotesURL(location); + + LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance("sl_about"); + if (floater_about) + { + floater_about->setSupportText(location); + } } class LLFloaterAboutListener: public LLEventAPI -- cgit v1.2.3 From de0a8782be1f95cb1ca5e74b38df0a73f69356c6 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 9 Aug 2016 16:23:27 +0300 Subject: MAINT-6614 Fixed typo in InventoryTrashMaxCapacity comment --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f1d0901a81..ca81696a50 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4870,7 +4870,7 @@ InventoryTrashMaxCapacity Comment - Maximum capacity of the Trash folder. User will ve offered to clean it up when exceeded. + Maximum capacity of the Trash folder. User will be offered to clean it up when exceeded. Persist 1 Type -- cgit v1.2.3 From 5924155f29d9c971dcec4fd21e77466a455ef98d Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 9 Aug 2016 19:29:14 +0300 Subject: MAINT-6612 Server release notes in Help --- indra/newview/llfloaterabout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 8d17f4c198..c2d0d9f06b 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -276,7 +276,7 @@ void LLFloaterAbout::handleServerReleaseNotes(LLSD results) } LLAppViewer::instance()->setServerReleaseNotesURL(location); - LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance("sl_about"); + LLFloaterAbout* floater_about = LLFloaterReg::findTypedInstance("sl_about"); if (floater_about) { floater_about->setSupportText(location); -- cgit v1.2.3 From e76b5643effc0a38c28a561ce403c97033419398 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 10 Aug 2016 13:31:25 +0300 Subject: MAINT-6608 FIXED URI parser problem with links with username, password --- indra/llcommon/lluriparser.cpp | 4 ++-- indra/llcommon/lluriparser.h | 2 +- indra/llui/llurlentry.cpp | 12 +++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index 82d0dc8b4b..c275b90120 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -205,9 +205,9 @@ void LLUriParser::glue(std::string& uri) const uri = first_part + second_part; } -void LLUriParser::glueFirst(std::string& uri) const +void LLUriParser::glueFirst(std::string& uri, bool use_scheme) const { - if (mScheme.size()) + if (use_scheme && mScheme.size()) { uri = mScheme; uri += "://"; diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h index 2df8085ae6..cfbf54f3c8 100644 --- a/indra/llcommon/lluriparser.h +++ b/indra/llcommon/lluriparser.h @@ -60,7 +60,7 @@ public: void extractParts(); void glue(std::string& uri) const; - void glueFirst(std::string& uri) const; + void glueFirst(std::string& uri, bool use_scheme = true) const; void glueSecond(std::string& uri) const; bool test() const; S32 normalize(); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e4848362a7..797fae81c4 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -205,9 +205,15 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const std::string label; up.extractParts(); - up.glueFirst(label); - std::string query = url.substr(label.size()); - return query; + up.glueFirst(label, false); + + size_t pos = url.find(label); + if (pos == std::string::npos) + { + return ""; + } + pos += label.size(); + return url.substr(pos); } -- cgit v1.2.3 From 1e2d10d13a90fcb79130f967c299e04ea664f0aa Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 10 Aug 2016 14:35:15 +0300 Subject: SL-437 Remove Checkbox from Abuse Report Submission --- indra/newview/llfloaterreporter.cpp | 28 +++++----------------- .../skins/default/xui/en/floater_report_abuse.xml | 10 +------- 2 files changed, 7 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index ed6f4ede9f..5d77972180 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -192,7 +192,6 @@ BOOL LLFloaterReporter::postBuild() mOwnerName = LLStringUtil::null; getChild("summary_edit")->setFocus(TRUE); - getChild("screen_check")->set(TRUE); mDefaultSummary = getChild("details_edit")->getValue().asString(); @@ -246,8 +245,6 @@ LLFloaterReporter::~LLFloaterReporter() // virtual void LLFloaterReporter::draw() { - getChildView("screen_check")->setEnabled(TRUE ); - LLFloater::draw(); } @@ -255,7 +252,6 @@ void LLFloaterReporter::enableControls(BOOL enable) { getChildView("category_combo")->setEnabled(enable); getChildView("chat_check")->setEnabled(enable); - getChildView("screen_check")->setEnabled(enable); getChildView("screenshot")->setEnabled(FALSE); getChildView("pick_btn")->setEnabled(enable); getChildView("summary_edit")->setEnabled(enable); @@ -452,19 +448,10 @@ void LLFloaterReporter::onClickSend(void *userdata) } else { - if(self->getChild("screen_check")->getValue()) - { - self->getChildView("send_btn")->setEnabled(FALSE); - self->getChildView("cancel_btn")->setEnabled(FALSE); - // the callback from uploading the image calls sendReportViaLegacy() - self->uploadImage(); - } - else - { - self->sendReportViaLegacy(self->gatherReport()); - LLUploadDialog::modalUploadFinished(); - self->closeFloater(); - } + self->getChildView("send_btn")->setEnabled(FALSE); + self->getChildView("cancel_btn")->setEnabled(FALSE); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); } } } @@ -713,10 +700,7 @@ LLSD LLFloaterReporter::gatherReport() // only send a screenshot ID if we're asked to and the email is // going to LL - Estate Owners cannot see the screenshot asset LLUUID screenshot_id = LLUUID::null; - if (getChild("screen_check")->getValue()) - { - screenshot_id = getChild("screenshot")->getValue(); - }; + screenshot_id = getChild("screenshot")->getValue(); LLSD report = LLSD::emptyMap(); report["report-type"] = (U8) mReportType; @@ -770,7 +754,7 @@ void LLFloaterReporter::finishedARPost(const LLSD &) void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) { - if(getChild("screen_check")->getValue().asBoolean() && !sshot_url.empty()) + if(!sshot_url.empty()) { // try to upload screenshot LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType)); diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index af62c7a9bc..225266af86 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -21,14 +21,6 @@ name="screenshot" top="15" width="220" /> - Reporter: -- cgit v1.2.3 From 78e1706ad06c4c32bcfac999398fc506c69eb9db Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 10 Aug 2016 18:18:34 +0300 Subject: MAINT-6569 Agent search was failing due to timeout --- indra/newview/llfloateravatarpicker.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 72892b47a4..aa7bfbfdb7 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -55,6 +55,8 @@ //#include "llsdserialize.h" +static const U32 AVATAR_PICKER_SEARCH_TIMEOUT = 180U; + //put it back as a member once the legacy path is out? static std::map sAvatarNameMap; @@ -463,10 +465,13 @@ void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::strin LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL; - LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + httpOpts->setTimeout(AVATAR_PICKER_SEARCH_TIMEOUT); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); -- cgit v1.2.3 From e3c58f74781186f084f60b35b931c5bb5d75e1ba Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 10 Aug 2016 19:02:57 +0300 Subject: MAINT-6554 reducing log spam --- indra/newview/llvovolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 50ccb2f74a..4aef6480cb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4451,7 +4451,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) { - LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; + LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) -- cgit v1.2.3 From 529778219388a445075880e86bc0e846004952c7 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 15 Aug 2016 17:05:23 +0300 Subject: MAINT-6634 "My graphics driver is out of date" was listed 3 times in Alerts --- indra/newview/llappviewer.cpp | 12 ++++-- .../newview/skins/default/xui/en/notifications.xml | 45 ++-------------------- indra/newview/skins/default/xui/en/strings.xml | 6 +++ 3 files changed, 18 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 950692a788..e1242513e1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1124,17 +1124,23 @@ bool LLAppViewer::init() #if LL_WINDOWS if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) { + std::string url; if (gGLManager.mIsIntel) { - LLNotificationsUtil::add("IntelOldDriver"); + url = LLTrans::getString("IntelDriverPage"); } else if (gGLManager.mIsNVIDIA) { - LLNotificationsUtil::add("NVIDIAOldDriver"); + url = LLTrans::getString("NVIDIADriverPage"); } else if (gGLManager.mIsATI) { - LLNotificationsUtil::add("AMDOldDriver"); + url = LLTrans::getString("AMDDriverPage"); + } + + if (!url.empty()) + { + LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url)); } } #endif diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 54e90ac496..6fdeedc8ae 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1638,14 +1638,14 @@ Visit [_URL] for more information? There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - Visit [_URL] to check for driver updates? + Visit [URL] to check for driver updates? confirm - http://www.intel.com/p/en_US/support/detect/graphics + [URL] fail - - There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - - Visit [_URL] to check for driver updates? - confirm - - http://support.amd.com/us/Pages/AMDSupportHub.aspx - - - fail - - - - There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - - Visit [_URL] to check for driver updates? - confirm - - http://www.nvidia.com/Download/index.aspx?lang=en-us - - - fail - - - Multiple Media Play/Pause Media + + http://www.intel.com/p/en_US/support/detect/graphics + http://www.nvidia.com/Download/index.aspx?lang=en-us + http://support.amd.com/us/Pages/AMDSupportHub.aspx + + An error was found parsing the command line. -- cgit v1.2.3 From 5b94ed9f4e8bff5d2079b012434d16df4ab27397 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 15 Aug 2016 20:01:56 +0300 Subject: MAINT-6634 fixed string --- indra/newview/llappviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e1242513e1..64bc7fb2c4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1131,7 +1131,7 @@ bool LLAppViewer::init() } else if (gGLManager.mIsNVIDIA) { - url = LLTrans::getString("NVIDIADriverPage"); + url = LLTrans::getString("NvidiaDriverPage"); } else if (gGLManager.mIsATI) { -- cgit v1.2.3 From 57060fa0ebfacf3705ec2d9770e83aab3c86b894 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 2 Aug 2016 21:57:04 +0300 Subject: MAINT-4124 Warning user about render-heavy set of HUDs --- indra/newview/app_settings/settings.xml | 55 +++++++++ indra/newview/llavatarrendernotifier.cpp | 130 +++++++++++++++++++++ indra/newview/llavatarrendernotifier.h | 36 ++++++ indra/newview/llvoavatar.cpp | 65 ++++++++++- .../newview/skins/default/xui/en/notifications.xml | 14 +++ indra/newview/skins/default/xui/en/strings.xml | 7 ++ 6 files changed, 302 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ca81696a50..00c769607f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10092,6 +10092,17 @@ Value 10 + ComplexityChangesPopUpDelay + + Comment + Delay before viewer will show avatar complexity notice again + Persist + 1 + Type + U32 + Value + 300 + RenderAvatarMaxComplexity Comment @@ -10104,6 +10115,50 @@ Value 0 + RenderHUDObjectsWarning + + Comment + Viewer will warn user about HUD containing to many objects if objects count is above this value + Persist + 1 + Type + U32 + Value + 1000 + + RenderHUDTexturesWarning + + Comment + Viewer will warn user about HUD containing to many textures if texture count is above this value + Persist + 1 + Type + U32 + Value + 200 + + RenderHUDOversizedTexturesWarning + + Comment + How many textures with size 1024 * 1024 or bigger HUD can contain before notifying user + Persist + 1 + Type + U32 + Value + 6 + + RenderHUDTexturesVirtualMemoryWarning + + Comment + Viewer will warn user about HUD textures using memory above this value (Virtual memory, in pixels) + Persist + 1 + Type + U32 + Value + 10000000 + RenderAutoMuteSurfaceAreaLimit Comment diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp index 24934fdb73..f7a1ef1621 100644 --- a/indra/newview/llavatarrendernotifier.cpp +++ b/indra/newview/llavatarrendernotifier.cpp @@ -51,6 +51,11 @@ static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1; // wait seconds before processing over limit updates after last complexity change static const U32 OVER_LIMIT_UPDATE_DELAY = 70; +static const U32 WARN_HUD_OBJECTS_LIMIT = 1000; +static const U32 WARN_HUD_TEXTURES_LIMIT = 200; +static const U32 WARN_HUD_OVERSIZED_TEXTURES_LIMIT = 6; +static const U32 WARN_HUD_TEXTURE_MEMORY_LIMIT = 10000000; // in pixels + LLAvatarRenderNotifier::LLAvatarRenderNotifier() : mAgentsCount(0), @@ -264,3 +269,128 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity) } } +// LLHUDRenderNotifier + +LLHUDRenderNotifier::LLHUDRenderNotifier() +{ +} + +LLHUDRenderNotifier::~LLHUDRenderNotifier() +{ +} + +void LLHUDRenderNotifier::updateNotificationHUD(LLHUDComplexity new_complexity) +{ + if (!isAgentAvatarValid()) + { + // data not ready. + return; + } + + static const char* hud_memory = "hud_render_memory_warning"; + static const char* hud_cost = "hud_render_cost_warning"; + static const char* hud_heavy = "hud_render_heavy_textures_warning"; + static const char* hud_cramped = "hud_render_cramped_warning"; + static const char* hud_textures = "hud_render_textures_warning"; + + static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); // ties max HUD cost to avatar cost + static LLCachedControl max_objects_count(gSavedSettings, "RenderHUDObjectsWarning", WARN_HUD_OBJECTS_LIMIT); + static LLCachedControl max_textures_count(gSavedSettings, "RenderHUDTexturesWarning", WARN_HUD_TEXTURES_LIMIT); + static LLCachedControl max_oversized_count(gSavedSettings, "RenderHUDOversizedTexturesWarning", WARN_HUD_OVERSIZED_TEXTURES_LIMIT); + static LLCachedControl max_texture_memory(gSavedSettings, "RenderHUDTexturesVirtualMemoryWarning", WARN_HUD_TEXTURE_MEMORY_LIMIT); + + if (mHUDPopUpDelayTimer.hasExpired()) + { + // Show warning with highest importance (5m delay between warnings by default) + // TODO: + // Consider showing message with list of issues. + // For now shows one after another if update arrives and timer expired, so + // consider showing only one most important or consider triggering not + // only in case of update + if (mReportedHUDComplexity.texturesSizeTotal < new_complexity.texturesSizeTotal + && new_complexity.texturesSizeTotal > max_texture_memory) + { + displayHUDNotification(hud_memory); + LL_DEBUGS("HUDdetail") << "HUD memory usage over limit," + << " was " << mReportedHUDComplexity.texturesSizeTotal + << " is " << new_complexity.texturesSizeTotal << LL_ENDL; + mReportedHUDComplexity.texturesSizeTotal = new_complexity.texturesSizeTotal; + } + else if ((mReportedHUDComplexity.objectsCost < new_complexity.objectsCost + || mReportedHUDComplexity.texturesCost < new_complexity.texturesCost) + && max_render_cost > 0 + && new_complexity.objectsCost + new_complexity.texturesCost > max_render_cost) + { + LL_DEBUGS("HUDdetail") << "HUD complexity over limit," + << " HUD textures cost: " << new_complexity.texturesCost + << " HUD objects cost: " << new_complexity.objectsCost << LL_ENDL; + displayHUDNotification(hud_cost); + mReportedHUDComplexity.objectsCost = new_complexity.objectsCost; + mReportedHUDComplexity.texturesCost = new_complexity.texturesCost; + } + else if (mReportedHUDComplexity.largeTexturesCount < new_complexity.largeTexturesCount + && new_complexity.largeTexturesCount > max_oversized_count) + { + LL_DEBUGS("HUDdetail") << "HUD contains to many large textures: " + << new_complexity.largeTexturesCount << LL_ENDL; + displayHUDNotification(hud_heavy); + mReportedHUDComplexity.largeTexturesCount = new_complexity.largeTexturesCount; + } + else if (mReportedHUDComplexity.texturesCount < new_complexity.texturesCount + && new_complexity.texturesCount > max_textures_count) + { + LL_DEBUGS("HUDdetail") << "HUD contains too many textures: " + << new_complexity.texturesCount << LL_ENDL; + displayHUDNotification(hud_cramped); + mReportedHUDComplexity.texturesCount = new_complexity.texturesCount; + } + else if (mReportedHUDComplexity.objectsCount < new_complexity.objectsCount + && new_complexity.objectsCount > max_objects_count) + { + LL_DEBUGS("HUDdetail") << "HUD contains too many objects: " + << new_complexity.objectsCount << LL_ENDL; + displayHUDNotification(hud_textures); + mReportedHUDComplexity.objectsCount = new_complexity.objectsCount; + } + else + { + // all warnings displayed, just store everything so that we will + // be able to reduce values and show warnings again later + mReportedHUDComplexity = new_complexity; + } + } + + if (mLatestHUDComplexity.objectsCost != new_complexity.objectsCost + || mLatestHUDComplexity.objectsCount != new_complexity.objectsCount + || mLatestHUDComplexity.texturesCost != new_complexity.texturesCost + || mLatestHUDComplexity.texturesCount != new_complexity.texturesCount + || mLatestHUDComplexity.largeTexturesCount != new_complexity.largeTexturesCount + || mLatestHUDComplexity.texturesSizeTotal != new_complexity.texturesSizeTotal) + { + LL_INFOS("HUDdetail") << "HUD textures count: " << new_complexity.texturesCount + << " HUD textures cost: " << new_complexity.texturesCost + << " Large textures: " << new_complexity.largeTexturesCount + << " HUD objects cost: " << new_complexity.objectsCost + << " HUD objects count: " << new_complexity.objectsCount << LL_ENDL; + + mLatestHUDComplexity = new_complexity; + } + +} + +void LLHUDRenderNotifier::displayHUDNotification(const char* message) +{ + static LLCachedControl pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300); + static LLCachedControl expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20); + LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay); + + LLSD args; + args["HUD_REASON"] = LLTrans::getString(message); + + LLNotifications::instance().add(LLNotification::Params() + .name("HUDComplexityWarning") + .expiry(expire_date) + .substitutions(args)); + mHUDPopUpDelayTimer.resetWithExpiry(pop_up_delay); +} + diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index 2a2704de28..959bebef02 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -33,6 +33,25 @@ class LLViewerRegion; +struct LLHUDComplexity +{ + LLHUDComplexity() + { + objectsCost = 0; + objectsCount = 0; + texturesCost = 0; + texturesCount = 0; + largeTexturesCount = 0; + texturesSizeTotal = 0; + } + U32 objectsCost; + U32 objectsCount; + U32 texturesCost; + U32 texturesCount; + U32 largeTexturesCount; + F64 texturesSizeTotal; +}; + // Class to notify user about drastic changes in agent's render weights or if other agents // reported that user's agent is too 'heavy' for their settings class LLAvatarRenderNotifier : public LLSingleton @@ -81,4 +100,21 @@ private: S32 mLastOutfitRezStatus; }; +// Class to notify user about heavy set of HUD +class LLHUDRenderNotifier : public LLSingleton +{ +public: + LLHUDRenderNotifier(); + ~LLHUDRenderNotifier(); + + void updateNotificationHUD(LLHUDComplexity new_complexity); + +private: + void displayHUDNotification(const char* message); + + LLHUDComplexity mReportedHUDComplexity; + LLHUDComplexity mLatestHUDComplexity; + LLFrameTimer mHUDPopUpDelayTimer; +}; + #endif /* ! defined(LL_llavatarrendernotifier_H) */ diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index cdc7e20c2c..aebc066507 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -186,6 +186,7 @@ const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0; +const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024; enum ERenderName { @@ -8356,6 +8357,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() { U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; + LLHUDComplexity hud_complexity; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { @@ -8432,6 +8434,55 @@ void LLVOAvatar::calculateUpdateRenderComplexity() } } } + if (isSelf() + && attached_object + && attached_object->isHUDAttachment() + && attached_object->mDrawable) + { + textures.clear(); + + const LLVOVolume* volume = attached_object->mDrawable->getVOVolume(); + if (volume) + { + // get cost and individual textures + hud_complexity.objectsCost += volume->getRenderCost(textures); + hud_complexity.objectsCount++; + + LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* childp = *iter; + const LLVOVolume* chld_volume = dynamic_cast(childp); + if (chld_volume) + { + // get cost and individual textures + hud_complexity.objectsCost += chld_volume->getRenderCost(textures); + hud_complexity.objectsCount++; + } + } + + hud_complexity.texturesCount += textures.size(); + + for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin(); + volume_texture != textures.end(); + ++volume_texture) + { + // add the cost of each individual texture (ignores duplicates) + hud_complexity.texturesCost += volume_texture->second; + LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first); + if (tex) + { + F64 size = tex->getMaxVirtualSize(); // in pixels + hud_complexity.texturesSizeTotal += size; + if (size >= HUD_OVERSIZED_TEXTURE_DATA_SIZE) + { + hud_complexity.largeTexturesCount++; + } + } + } + } + } } } @@ -8493,11 +8544,15 @@ void LLVOAvatar::calculateUpdateRenderComplexity() static LLCachedControl show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20); - if (isSelf() && show_my_complexity_changes) - { - LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity); - } - } + if (isSelf() && show_my_complexity_changes) + { + // Avatar complexity + LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity); + + // HUD complexity + LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity); + } + } } void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6fdeedc8ae..102ce0ddc0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3319,6 +3319,20 @@ Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Renderin Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 avatar complexity] is [AGENT_COMPLEXITY]. + + + HUDComplexityWarning + + [HUD_REASON], it is likely to negatively affect your performance. + + + You may not be rendered by most of those around you. You may not be rendered by anyone around you. + + Your HUD uses a lot of texture memory + Your HUD contains a lot of expensive objects and textures + Your HUD contains a lot of large textures + Your HUD contains too many objects + Your HUD contains too many textures + - - - + id="30689" + group="1" + name="EyeBone_Big_Eyes" + value_min="-1.1" + value_max="1.1"> + + + + - + - - + + + Date: Tue, 9 Aug 2016 09:17:37 -0400 Subject: SL-126 - attachment logging under avatar at DEBUG level. Also fixed a typo in avatar_lad.xml --- indra/newview/character/avatar_lad.xml | 2 +- indra/newview/llvoavatar.cpp | 4 ++-- indra/newview/llvovolume.cpp | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 533ef95d3e..a9f506d80b 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -871,7 +871,7 @@ offset="-0.02 0 0" /> diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d3cd85e9f4..b1282fb4de 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5606,11 +5606,11 @@ void LLVOAvatar::showAttachmentPosOverrides(bool verbose) const { std::stringstream ss; std::copy(joint_names.begin(), joint_names.end(), std::ostream_iterator(ss, ",")); - LL_INFOS() << getFullname() << " attachment positions defined for joints: " << ss.str() << "\n" << LL_ENDL; + LL_DEBUGS("Avatar") << getFullname() << " attachment positions defined for joints: " << ss.str() << "\n" << LL_ENDL; } else { - LL_INFOS() << getFullname() << " no attachment positions defined for any joints" << "\n" << LL_ENDL; + LL_DEBUGS("Avatar") << getFullname() << " no attachment positions defined for any joints" << "\n" << LL_ENDL; } if (!verbose) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 465f8fe0d6..c8e98683aa 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4783,7 +4783,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) pAvatarVO->addAttachmentPosOverridesForObject(vobj); if (pAvatarVO->isSelf()) { - //pAvatarVO->showAttachmentPosOverrides(); + bool verbose = true; + pAvatarVO->showAttachmentPosOverrides(verbose); } } -- cgit v1.2.3 From 95d9e85f9539c449f37c438b90a90e6ac73d3b87 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 9 Aug 2016 15:24:09 -0400 Subject: SL-109 - made viewer much less tolerant of bad data in avatar_skeleton.xml or avatar_lad.xml. If either of these is broken, there's no point trying to continue, more informative to just error out with an appropriate message. --- indra/llappearance/llavatarappearance.cpp | 41 +++++++++++++------------ indra/llappearance/llpolyskeletaldistortion.cpp | 4 ++- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2ce43436db..acb43d23a1 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -593,7 +593,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent { if (volume_num >= (S32)mNumCollisionVolumes) { - LL_WARNS() << "Too many bones" << LL_ENDL; + LL_WARNS() << "Too many collision volumes" << LL_ENDL; return FALSE; } joint = (&mCollisionVolumes[volume_num]); @@ -866,21 +866,21 @@ BOOL LLAvatarAppearance::loadAvatar() // avatar_skeleton.xml if( !buildSkeleton(sAvatarSkeletonInfo) ) { - LL_WARNS() << "avatar file: buildSkeleton() failed" << LL_ENDL; + LL_ERRS() << "avatar file: buildSkeleton() failed" << LL_ENDL; return FALSE; } // avatar_lad.xml : if( !loadSkeletonNode() ) { - LL_WARNS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL; + LL_ERRS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL; return FALSE; } // avatar_lad.xml : if( !loadMeshNodes() ) { - LL_WARNS() << "avatar file: loadNodeMesh() failed" << LL_ENDL; + LL_ERRS() << "avatar file: loadNodeMesh() failed" << LL_ENDL; return FALSE; } @@ -890,13 +890,13 @@ BOOL LLAvatarAppearance::loadAvatar() mTexSkinColor = new LLTexGlobalColor( this ); if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) { - LL_WARNS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL; + LL_ERRS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL; return FALSE; } } else { - LL_WARNS() << " name=\"skin_color\" not found" << LL_ENDL; + LL_ERRS() << " name=\"skin_color\" not found" << LL_ENDL; return FALSE; } if( sAvatarXmlInfo->mTexHairColorInfo ) @@ -904,13 +904,13 @@ BOOL LLAvatarAppearance::loadAvatar() mTexHairColor = new LLTexGlobalColor( this ); if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) { - LL_WARNS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL; + LL_ERRS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL; return FALSE; } } else { - LL_WARNS() << " name=\"hair_color\" not found" << LL_ENDL; + LL_ERRS() << " name=\"hair_color\" not found" << LL_ENDL; return FALSE; } if( sAvatarXmlInfo->mTexEyeColorInfo ) @@ -918,26 +918,26 @@ BOOL LLAvatarAppearance::loadAvatar() mTexEyeColor = new LLTexGlobalColor( this ); if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) { - LL_WARNS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL; + LL_ERRS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL; return FALSE; } } else { - LL_WARNS() << " name=\"eye_color\" not found" << LL_ENDL; + LL_ERRS() << " name=\"eye_color\" not found" << LL_ENDL; return FALSE; } // avatar_lad.xml : if (sAvatarXmlInfo->mLayerInfoList.empty()) { - LL_WARNS() << "avatar file: missing node" << LL_ENDL; + LL_ERRS() << "avatar file: missing node" << LL_ENDL; return FALSE; } if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) { - LL_WARNS() << "avatar file: missing node" << LL_ENDL; + LL_ERRS() << "avatar file: missing node" << LL_ENDL; return FALSE; } @@ -1136,6 +1136,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() { // This should never happen LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; + return FALSE; } } else @@ -1730,7 +1731,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "Unknown param type." << LL_ENDL; } - continue; + return FALSE; } LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; @@ -1755,7 +1756,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No name supplied for attachment point." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); @@ -1763,7 +1764,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); @@ -1789,7 +1790,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); @@ -1875,7 +1876,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Unknown param type." << LL_ENDL; } - continue; + return FALSE; } LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); @@ -2036,7 +2037,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No name supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); @@ -2044,7 +2045,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No region supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); @@ -2052,7 +2053,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL; delete info; - continue; + return FALSE; } // optional parameter. don't throw a warning if not present. diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index e9750ae6f5..8d71335175 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -150,8 +150,10 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); if (!joint) { + // There's no point continuing after this error - means + // that either the skeleton or lad file is broken. LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL; - continue; + return FALSE; } // store it -- cgit v1.2.3 From 85a13b53f5570c44c476a7af70846874dfc3ecbf Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Aug 2016 14:20:44 -0400 Subject: MAINT-6631 - reluctantly, added support for animation of collision volumes, to avoid breaking existing content. --- indra/llappearance/llavatarappearance.cpp | 6 ++++-- indra/llappearance/llavatarappearance.h | 2 ++ indra/llcharacter/lljoint.h | 7 ++++--- indra/newview/llvoavatar.cpp | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index acb43d23a1..f9745efb78 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -186,7 +186,8 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mPelvisToFoot(0.f), mHeadOffset(), mRoot(NULL), - mWearableData(wearable_data) + mWearableData(wearable_data), + mNextJointNum(0) { llassert_always(mWearableData); mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); @@ -625,6 +626,8 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent volume_num++; } + joint->setJointNum(mNextJointNum++); + // setup children LLAvatarBoneInfo::child_list_t::const_iterator iter; for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) @@ -1276,7 +1279,6 @@ LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num ) if (!mSkeleton[num]) { mSkeleton[num] = createAvatarJoint(); - mSkeleton[num]->setJointNum(num); } return mSkeleton[num]; } diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 3865da7098..dbcc1bfcf0 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -139,6 +139,8 @@ public: typedef std::map joint_map_t; joint_map_t mJointMap; + + S32 mNextJointNum; void computeBodySize(); diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2afdef1026..b2736f6c1e 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,9 +40,10 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; -// Need to set this to count of animate-able joints (currently #bones + -// #attachments) + 2, rounded to next multiple of 4. -const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 192; // must be divisible by 4! +// Need to set this to count of animate-able joints, +// currently = #bones + #collision_volumes + #attachments + 2, +// rounded to next multiple of 4. +const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 216; // must be divisible by 4! const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; // These should be higher than the joint_num of any diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b1282fb4de..6e436e85e9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5921,7 +5921,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) attachment->setVisibleInFirstPerson(info->mVisibleFirstPerson); attachment->setIsHUDAttachment(info->mIsHUDAttachment); // attachment can potentially be animated, needs a number. - attachment->setJointNum(mSkeleton.size() + attachmentID - 1); + attachment->setJointNum(mNextJointNum++); if (newly_created) { -- cgit v1.2.3 From b25ee9095deca0cd0c7eedafda89e021734d0ca7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 15 Aug 2016 14:13:56 -0400 Subject: Remove VSTool, its build info and all invocations. VSTool manipulates the SecondLife.sln solution file for the convenience of a developer subsequently running Visual Studio interactively. But the cost of having it sometimes break TeamCity automated builds is too high -- especially since we never expect to run Visual Studio interactively on a TC build host. Also remove the CMake UNATTENDED variable that controlled it. --- indra/cmake/Variables.cmake | 1 - indra/newview/CMakeLists.txt | 15 - indra/tools/vstool/DispatchUtility.cs | 271 ------------- indra/tools/vstool/README.txt | 9 - indra/tools/vstool/VSTool.csproj | 98 ----- indra/tools/vstool/VSTool.exe | Bin 24576 -> 0 bytes indra/tools/vstool/VSTool.sln | 19 - indra/tools/vstool/app.config | 3 - indra/tools/vstool/main.cs | 729 ---------------------------------- 9 files changed, 1145 deletions(-) delete mode 100644 indra/tools/vstool/DispatchUtility.cs delete mode 100644 indra/tools/vstool/README.txt delete mode 100755 indra/tools/vstool/VSTool.csproj delete mode 100755 indra/tools/vstool/VSTool.exe delete mode 100755 indra/tools/vstool/VSTool.sln delete mode 100644 indra/tools/vstool/app.config delete mode 100755 indra/tools/vstool/main.cs (limited to 'indra') diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 63e296b556..8292a0c63d 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -164,7 +164,6 @@ set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside") set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Linden-supplied prebuilt libraries.") -set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.") set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dce0ea73cd..586a56b49a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1799,21 +1799,6 @@ if (WINDOWS) windows-crash-logger ) - # sets the 'working directory' for debugging from visual studio. - if (NOT UNATTENDED) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe - ARGS - --solution - ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln - --workingdir - ${VIEWER_BINARY_NAME} - "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." - ) - endif (NOT UNATTENDED) - if (PACKAGE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2 diff --git a/indra/tools/vstool/DispatchUtility.cs b/indra/tools/vstool/DispatchUtility.cs deleted file mode 100644 index 6056ac55a1..0000000000 --- a/indra/tools/vstool/DispatchUtility.cs +++ /dev/null @@ -1,271 +0,0 @@ -#region Using Directives - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Reflection; -using System.Security.Permissions; - -#endregion - -namespace TestDispatchUtility -{ - /// - /// Provides helper methods for working with COM IDispatch objects that have a registered type library. - /// - public static class DispatchUtility - { - #region Private Constants - - private const int S_OK = 0; //From WinError.h - private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800 - - #endregion - - #region Public Methods - - /// - /// Gets whether the specified object implements IDispatch. - /// - /// An object to check. - /// True if the object implements IDispatch. False otherwise. - public static bool ImplementsIDispatch(object obj) - { - bool result = obj is IDispatchInfo; - return result; - } - - /// - /// Gets a Type that can be used with reflection. - /// - /// An object that implements IDispatch. - /// Whether an exception should be thrown if a Type can't be obtained. - /// A .NET Type that can be used with reflection. - /// If doesn't implement IDispatch. - [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static Type GetType(object obj, bool throwIfNotFound) - { - RequireReference(obj, "obj"); - Type result = GetType((IDispatchInfo)obj, throwIfNotFound); - return result; - } - - /// - /// Tries to get the DISPID for the requested member name. - /// - /// An object that implements IDispatch. - /// The name of a member to lookup. - /// If the method returns true, this holds the DISPID on output. - /// If the method returns false, this value should be ignored. - /// True if the member was found and resolved to a DISPID. False otherwise. - /// If doesn't implement IDispatch. - [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static bool TryGetDispId(object obj, string name, out int dispId) - { - RequireReference(obj, "obj"); - bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId); - return result; - } - - /// - /// Invokes a member by DISPID. - /// - /// An object that implements IDispatch. - /// The DISPID of a member. This can be obtained using - /// . - /// The arguments to pass to the member. - /// The member's return value. - /// - /// This can invoke a method or a property get accessor. - /// - public static object Invoke(object obj, int dispId, object[] args) - { - string memberName = "[DispId=" + dispId + "]"; - object result = Invoke(obj, memberName, args); - return result; - } - - /// - /// Invokes a member by name. - /// - /// An object. - /// The name of the member to invoke. - /// The arguments to pass to the member. - /// The member's return value. - /// - /// This can invoke a method or a property get accessor. - /// - public static object Invoke(object obj, string memberName, object[] args) - { - RequireReference(obj, "obj"); - Type type = obj.GetType(); - object result = type.InvokeMember(memberName, BindingFlags.InvokeMethod | BindingFlags.GetProperty, - null, obj, args, null); - return result; - } - - #endregion - - #region Private Methods - - /// - /// Requires that the value is non-null. - /// - /// The type of the value. - /// The value to check. - /// The name of the value. - private static void RequireReference(T value, string name) where T : class - { - if (value == null) - { - throw new ArgumentNullException(name); - } - } - - /// - /// Gets a Type that can be used with reflection. - /// - /// An object that implements IDispatch. - /// Whether an exception should be thrown if a Type can't be obtained. - /// A .NET Type that can be used with reflection. - private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound) - { - RequireReference(dispatch, "dispatch"); - - Type result = null; - int typeInfoCount; - int hr = dispatch.GetTypeInfoCount(out typeInfoCount); - if (hr == S_OK && typeInfoCount > 0) - { - // Type info isn't usually culture-aware for IDispatch, so we might as well pass - // the default locale instead of looking up the current thread's LCID each time - // (via CultureInfo.CurrentCulture.LCID). - dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result); - } - - if (result == null && throwIfNotFound) - { - // If the GetTypeInfoCount called failed, throw an exception for that. - Marshal.ThrowExceptionForHR(hr); - - // Otherwise, throw the same exception that Type.GetType would throw. - throw new TypeLoadException(); - } - - return result; - } - - /// - /// Tries to get the DISPID for the requested member name. - /// - /// An object that implements IDispatch. - /// The name of a member to lookup. - /// If the method returns true, this holds the DISPID on output. - /// If the method returns false, this value should be ignored. - /// True if the member was found and resolved to a DISPID. False otherwise. - private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId) - { - RequireReference(dispatch, "dispatch"); - RequireReference(name, "name"); - - bool result = false; - - // Members names aren't usually culture-aware for IDispatch, so we might as well - // pass the default locale instead of looking up the current thread's LCID each time - // (via CultureInfo.CurrentCulture.LCID). - Guid iidNull = Guid.Empty; - int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId); - - const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h - const int DISPID_UNKNOWN = -1; //From OAIdl.idl - if (hr == S_OK) - { - result = true; - } - else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN) - { - // This is the only supported "error" case because it means IDispatch - // is saying it doesn't know the member we asked about. - result = false; - } - else - { - // The other documented result codes are all errors. - Marshal.ThrowExceptionForHR(hr); - } - - return result; - } - - #endregion - - #region Private Interfaces - - /// - /// A partial declaration of IDispatch used to lookup Type information and DISPIDs. - /// - /// - /// This interface only declares the first three methods of IDispatch. It omits the - /// fourth method (Invoke) because there are already plenty of ways to do dynamic - /// invocation in .NET. But the first three methods provide dynamic type metadata - /// discovery, which .NET doesn't provide normally if you have a System.__ComObject - /// RCW instead of a strongly-typed RCW. - /// - /// Note: The original declaration of IDispatch is in OAIdl.idl. - /// - [ComImport] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [Guid("00020400-0000-0000-C000-000000000046")] - private interface IDispatchInfo - { - /// - /// Gets the number of Types that the object provides (0 or 1). - /// - /// Returns 0 or 1 for the number of Types provided by . - /// - /// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85) - /// - [PreserveSig] - int GetTypeInfoCount(out int typeInfoCount); - - /// - /// Gets the Type information for an object if returned 1. - /// - /// Must be 0. - /// Typically, LOCALE_SYSTEM_DEFAULT (2048). - /// Returns the object's Type information. - /// - /// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85) - /// - void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, - MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo); - - /// - /// Gets the DISPID of the specified member name. - /// - /// Must be IID_NULL. Pass a copy of Guid.Empty. - /// The name of the member to look up. - /// Must be 1. - /// Typically, LOCALE_SYSTEM_DEFAULT (2048). - /// If a member with the requested - /// is found, this returns its DISPID and the method's return value is 0. - /// If the method returns a non-zero value, then this parameter's output value is - /// undefined. - /// Zero for success. Non-zero for failure. - /// - /// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85) - /// - [PreserveSig] - int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId); - - // NOTE: The real IDispatch also has an Invoke method next, but we don't need it. - // We can invoke methods using .NET's Type.InvokeMember method with the special - // [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo - // and invoke methods on that through reflection. - // Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx - } - - #endregion - } -} diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt deleted file mode 100644 index e419180031..0000000000 --- a/indra/tools/vstool/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -VSTool is a command line utility to manipulate VisualStudio settings. - -The windows cmake project configuration uses VSTool.exe - -A handy upgrade: - figure out how to make cmake build this csharp app - - or write the app using script (jscript?!?) so it doesn't need to be built. - - diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj deleted file mode 100755 index 7f431e85c7..0000000000 --- a/indra/tools/vstool/VSTool.csproj +++ /dev/null @@ -1,98 +0,0 @@ - - - - Local - 8.0.50727 - 2.0 - {96943E2D-1373-4617-A117-D0F997A94919} - Debug - AnyCPU - - - - - VSTool - - - JScript - Grid - IE50 - false - Exe - VSTool - Always - VSTool.VSToolMain - - - - - v2.0 - 2.0 - - - .\ - false - 285212672 - false - - - DEBUG;TRACE - - - true - 4096 - false - - - false - false - false - false - 4 - full - prompt - - - .\ - false - 285212672 - false - - - TRACE - - - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - - - - System - - - System.Data - - - - - Code - - - - - - - - - - \ No newline at end of file diff --git a/indra/tools/vstool/VSTool.exe b/indra/tools/vstool/VSTool.exe deleted file mode 100755 index 854290b90a..0000000000 Binary files a/indra/tools/vstool/VSTool.exe and /dev/null differ diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln deleted file mode 100755 index 21e3d75971..0000000000 --- a/indra/tools/vstool/VSTool.sln +++ /dev/null @@ -1,19 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/indra/tools/vstool/app.config b/indra/tools/vstool/app.config deleted file mode 100644 index 8494f728ff..0000000000 --- a/indra/tools/vstool/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs deleted file mode 100755 index ef2e582b90..0000000000 --- a/indra/tools/vstool/main.cs +++ /dev/null @@ -1,729 +0,0 @@ -// Code about getting running instances visual studio -// was borrowed from -// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using Microsoft.CSharp; - -namespace VSTool -{ - // The MessageFilter class comes from: - // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx - // It allows vstool to get timing error messages from - // visualstudio and handle them. - public class MessageFilter : IOleMessageFilter - { - // - // Class containing the IOleMessageFilter - // thread error-handling functions. - - // Start the filter. - public static void Register() - { - IOleMessageFilter newFilter = new MessageFilter(); - IOleMessageFilter oldFilter = null; - CoRegisterMessageFilter(newFilter, out oldFilter); - } - - // Done with the filter, close it. - public static void Revoke() - { - IOleMessageFilter oldFilter = null; - CoRegisterMessageFilter(null, out oldFilter); - } - - // - // IOleMessageFilter functions. - // Handle incoming thread requests. - int IOleMessageFilter.HandleInComingCall(int dwCallType, - System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr - lpInterfaceInfo) - { - //Return the flag SERVERCALL_ISHANDLED. - return 0; - } - - // Thread call was rejected, so try again. - int IOleMessageFilter.RetryRejectedCall(System.IntPtr - hTaskCallee, int dwTickCount, int dwRejectType) - { - if (dwRejectType == 2) - // flag = SERVERCALL_RETRYLATER. - { - // Retry the thread call immediately if return >=0 & - // <100. - return 99; - } - // Too busy; cancel call. - return -1; - } - - int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, - int dwTickCount, int dwPendingType) - { - //Return the flag PENDINGMSG_WAITDEFPROCESS. - return 2; - } - - // Implement the IOleMessageFilter interface. - [DllImport("Ole32.dll")] - private static extern int - CoRegisterMessageFilter(IOleMessageFilter newFilter, out - IOleMessageFilter oldFilter); - } - - [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), - InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - interface IOleMessageFilter - { - [PreserveSig] - int HandleInComingCall( - int dwCallType, - IntPtr hTaskCaller, - int dwTickCount, - IntPtr lpInterfaceInfo); - - [PreserveSig] - int RetryRejectedCall( - IntPtr hTaskCallee, - int dwTickCount, - int dwRejectType); - - [PreserveSig] - int MessagePending( - IntPtr hTaskCallee, - int dwTickCount, - int dwPendingType); - } - - class ViaCOM - { - public static object GetProperty(object from_obj, string prop_name) - { - try - { - Type objType = from_obj.GetType(); - return objType.InvokeMember( - prop_name, - BindingFlags.GetProperty, null, - from_obj, - null); - } - catch (Exception e) - { - Console.WriteLine("Error getting property: \"{0}\"", prop_name); - Console.WriteLine(e.Message); - throw e; - } - } - - public static object SetProperty(object from_obj, string prop_name, object new_value) - { - try - { - object[] args = { new_value }; - Type objType = from_obj.GetType(); - return objType.InvokeMember( - prop_name, - BindingFlags.DeclaredOnly | - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.SetProperty, - null, - from_obj, - args); - } - catch (Exception e) - { - Console.WriteLine("Error setting property: \"{0}\"", prop_name); - Console.WriteLine(e.Message); - throw e; - } - } - - public static object CallMethod(object from_obj, string method_name, params object[] args) - { - try - { - Type objType = from_obj.GetType(); - return objType.InvokeMember( - method_name, - BindingFlags.DeclaredOnly | - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.InvokeMethod, - null, - from_obj, - args); - } - catch (Exception e) - { - Console.WriteLine("Error calling method \"{0}\"", method_name); - Console.WriteLine(e.Message); - throw e; - } - } - }; - - /// - /// The main entry point class for VSTool. - /// - class VSToolMain - { - #region Interop imports - [DllImport("ole32.dll")] - public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); - - [DllImport("ole32.dll")] - public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); - #endregion - - static System.Boolean ignore_case = true; - - static string solution_name = null; - static bool use_new_vs = false; - static Hashtable projectDict = new Hashtable(); - static string startup_project = null; - static string config = null; - - static object dte = null; - static object solution = null; - - /// - /// The main entry point for the application. - /// - [STAThread] - static int Main(string[] args) - { - int retVal = 0; - bool need_save = false; - - try - { - parse_command_line(args); - - Console.WriteLine("Editing solution: {0}", solution_name); - - bool found_open_solution = GetDTEAndSolution(); - - if (dte == null || solution == null) - { - retVal = 1; - } - else - { - MessageFilter.Register(); - - // Walk through all of the projects in the solution - // and list the type of each project. - foreach (DictionaryEntry p in projectDict) - { - string project_name = (string)p.Key; - string working_dir = (string)p.Value; - if (SetProjectWorkingDir(solution, project_name, working_dir)) - { - need_save = true; - } - } - - if (config != null) - { - need_save = SetActiveConfig(config); - } - - if (startup_project != null) - { - need_save = SetStartupProject(startup_project); - } - - if (need_save) - { - if (found_open_solution == false) - { - ViaCOM.CallMethod(solution, "Close", null); - } - } - } - } - catch (Exception e) - { - Console.WriteLine(e.Message); - retVal = 1; - } - finally - { - if (solution != null) - { - Marshal.ReleaseComObject(solution); - solution = null; - } - - if (dte != null) - { - Marshal.ReleaseComObject(dte); - dte = null; - } - - MessageFilter.Revoke(); - } - return retVal; - } - - public static bool parse_command_line(string[] args) - { - string options_desc = - "--solution : MSVC solution name. (required)\n" + - "--use_new_vs : Ignore running versions of visual studio.\n" + - "--workingdir : Set working dir of a VC project.\n" + - "--config : Set the active config for the solution.\n" + - "--startup : Set the startup project for the solution.\n"; - - try - { - // Command line param parsing loop. - int i = 0; - for (; i < args.Length; ++i) - { - if ("--solution" == args[i]) - { - if (solution_name != null) - { - throw new ApplicationException("Found second --solution option"); - } - solution_name = args[++i]; - } - else if ("--use_new_vs" == args[i]) - { - use_new_vs = true; - } - - else if ("--workingdir" == args[i]) - { - string project_name = args[++i]; - string working_dir = args[++i]; - projectDict.Add(project_name, working_dir); - } - else if ("--config" == args[i]) - { - if (config != null) - { - throw new ApplicationException("Found second --config option"); - } - config = args[++i]; - } - else if ("--startup" == args[i]) - { - if (startup_project != null) - { - throw new ApplicationException("Found second --startup option"); - } - startup_project = args[++i]; - } - else - { - throw new ApplicationException("Found unrecognized token on command line: " + args[i]); - } - } - - if (solution_name == null) - { - throw new ApplicationException("The --solution option is required."); - } - } - catch(ApplicationException e) - { - - Console.WriteLine("Oops! " + e.Message); - Console.Write("Command line:"); - foreach (string arg in args) - { - Console.Write(" " + arg); - } - Console.Write("\n\n"); - Console.WriteLine("VSTool command line usage"); - Console.Write(options_desc); - throw e; - } - return true; - } - - public static bool GetDTEAndSolution() - { - bool found_open_solution = true; - - Console.WriteLine("Looking for existing VisualStudio instance..."); - - // Get an instance of the currently running Visual Studio .NET IDE. - // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1"); - string full_solution_name = System.IO.Path.GetFullPath(solution_name); - if (false == use_new_vs) - { - dte = GetIDEInstance(full_solution_name); - } - - if (dte == null) - { - try - { - Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance..."); - Console.WriteLine(" Reading .sln file version..."); - string version = GetSolutionVersion(full_solution_name); - - Console.WriteLine(" Using version: {0}...", version); - string progid = GetVSProgID(version); - - Type objType = Type.GetTypeFromProgID(progid); - dte = System.Activator.CreateInstance(objType); - Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name); - - solution = ViaCOM.GetProperty(dte, "Solution"); - object[] openArgs = { full_solution_name }; - ViaCOM.CallMethod(solution, "Open", openArgs); - } - catch (Exception e) - { - Console.WriteLine(e.Message); - Console.WriteLine("Quitting do to error opening: {0}", full_solution_name); - solution = null; - dte = null; - return found_open_solution; - } - found_open_solution = false; - } - - if (solution == null) - { - solution = ViaCOM.GetProperty(dte, "Solution"); - } - - return found_open_solution; - } - - /// - /// Get the DTE object for the instance of Visual Studio IDE that has - /// the specified solution open. - /// - /// The absolute filename of the solution - /// Corresponding DTE object or null if no such IDE is running - public static object GetIDEInstance( string solutionFile ) - { - Hashtable runningInstances = GetIDEInstances( true ); - IDictionaryEnumerator enumerator = runningInstances.GetEnumerator(); - - while ( enumerator.MoveNext() ) - { - try - { - object ide = enumerator.Value; - if (ide != null) - { - object sol = ViaCOM.GetProperty(ide, "Solution"); - if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case)) - { - return ide; - } - } - } - catch{} - } - - return null; - } - - /// - /// Get a table of the currently running instances of the Visual Studio .NET IDE. - /// - /// Only return instances that have opened a solution - /// A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object - public static Hashtable GetIDEInstances( bool openSolutionsOnly ) - { - Hashtable runningIDEInstances = new Hashtable(); - Hashtable runningObjects = GetRunningObjectTable(); - - IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); - while ( rotEnumerator.MoveNext() ) - { - string candidateName = (string) rotEnumerator.Key; - if (!candidateName.StartsWith("!VisualStudio.DTE")) - continue; - - object ide = rotEnumerator.Value; - if (ide == null) - continue; - - if (openSolutionsOnly) - { - try - { - object sol = ViaCOM.GetProperty(ide, "Solution"); - string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName"); - if (solutionFile != String.Empty) - { - runningIDEInstances[ candidateName ] = ide; - } - } - catch {} - } - else - { - runningIDEInstances[ candidateName ] = ide; - } - } - return runningIDEInstances; - } - - /// - /// Get a snapshot of the running object table (ROT). - /// - /// A hashtable mapping the name of the object in the ROT to the corresponding object - [STAThread] - public static Hashtable GetRunningObjectTable() - { - Hashtable result = new Hashtable(); - - int numFetched = 0; - IRunningObjectTable runningObjectTable; - IEnumMoniker monikerEnumerator; - IMoniker[] monikers = new IMoniker[1]; - - GetRunningObjectTable(0, out runningObjectTable); - runningObjectTable.EnumRunning(out monikerEnumerator); - monikerEnumerator.Reset(); - - while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0) - { - IBindCtx ctx; - CreateBindCtx(0, out ctx); - - string runningObjectName; - monikers[0].GetDisplayName(ctx, null, out runningObjectName); - - object runningObjectVal; - runningObjectTable.GetObject( monikers[0], out runningObjectVal); - - result[ runningObjectName ] = runningObjectVal; - } - - return result; - } - - public static string GetSolutionVersion(string solutionFullFileName) - { - string version; - System.IO.StreamReader solutionStreamReader = null; - string firstLine; - string format; - - try - { - solutionStreamReader = new System.IO.StreamReader(solutionFullFileName); - do - { - firstLine = solutionStreamReader.ReadLine(); - } - while (firstLine == ""); - - format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim(); - - switch(format) - { - case "7.00": - version = "VC70"; - break; - - case "8.00": - version = "VC71"; - break; - - case "9.00": - version = "VC80"; - break; - - case "10.00": - version = "VC90"; - break; - - case "11.00": - version = "VC100"; - break; - - case "12.00": - version = "VC120"; - break; - - default: - throw new ApplicationException("Unknown .sln version: " + format); - } - } - finally - { - if(solutionStreamReader != null) - { - solutionStreamReader.Close(); - } - } - - return version; - } - - public static string GetVSProgID(string version) - { - string progid = null; - switch(version) - { - case "VC70": - progid = "VisualStudio.DTE.7"; - break; - - case "VC71": - progid = "VisualStudio.DTE.7.1"; - break; - - case "VC80": - progid = "VisualStudio.DTE.8.0"; - break; - - case "VC90": - progid = "VisualStudio.DTE.9.0"; - break; - - case "VC100": - progid = "VisualStudio.DTE.10.0"; - break; - - case "VC120": - progid = "VisualStudio.DTE.12.0"; - break; - - default: - throw new ApplicationException("Can't handle VS version: " + version); - } - - return progid; - } - - public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir) - { - bool made_change = false; - Console.WriteLine("Looking for project {0}...", project_name); - try - { - object prjs = ViaCOM.GetProperty(sol, "Projects"); - object count = ViaCOM.GetProperty(prjs, "Count"); - for(int i = 1; i <= (int)count; ++i) - { - object[] prjItemArgs = { (object)i }; - object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs); - string name = (string)ViaCOM.GetProperty(prj, "Name"); - if (0 == string.Compare(name, project_name, ignore_case)) - { - Console.WriteLine("Found project: {0}", project_name); - Console.WriteLine("Setting working directory"); - - string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName"); - Console.WriteLine(full_project_name); - - // *NOTE:Mani Thanks to incompatibilities between different versions of the - // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to - // the VCProjectEngine types from a different version than the one built - // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built - // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, - // without the type casting. Its tedious code, but it seems to work. - - // oCfgs should be assigned to a 'Project.Configurations' collection. - object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations"); - - // oCount will be assigned to the number of configs present in oCfgs. - object oCount = ViaCOM.GetProperty(oCfgs, "Count"); - - for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex) - { - object[] itemArgs = {(object)cfgIndex}; - object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs); - object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings"); - ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir); - } - - break; - } - } - made_change = true; - } - catch( Exception e ) - { - Console.WriteLine(e.Message); - Console.WriteLine("Failed to set working dir for project, {0}.", project_name); - } - - return made_change; - } - - public static bool SetStartupProject(string startup_project) - { - bool result = false; - try - { - // You need the 'unique name of the project to set StartupProjects. - // find the project by generic name. - Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project); - object prjs = ViaCOM.GetProperty(solution, "Projects"); - object count = ViaCOM.GetProperty(prjs, "Count"); - for (int i = 1; i <= (int)count; ++i) - { - object[] itemArgs = { (object)i }; - object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs); - object prjName = ViaCOM.GetProperty(prj, "Name"); - if (0 == string.Compare((string)prjName, startup_project, ignore_case)) - { - object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); - ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName")); - Console.WriteLine(" Success!"); - result = true; - break; - } - } - - if (result == false) - { - Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project); - } - } - catch (Exception e) - { - Console.WriteLine(" Failed to set the startup project!"); - Console.WriteLine(e.Message); - } - return result; - } - - public static bool SetActiveConfig(string config) - { - bool result = false; - try - { - Console.WriteLine("Trying to set active config to \"{0}\"", config); - object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); - object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations"); - object[] itemArgs = { (object)config }; - object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs); - ViaCOM.CallMethod(solCfg, "Activate", null); - Console.WriteLine(" Success!"); - result = true; - } - catch (Exception e) - { - Console.WriteLine(" Failed to set \"{0}\" as the active config.", config); - Console.WriteLine(e.Message); - } - return result; - } - } -} -- cgit v1.2.3 From 454da876dc648d34aacf27217952e640f4fdaa88 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 15 Aug 2016 17:12:37 -0400 Subject: Backed out changeset e187a6b45ce6: restored VSTool et al. --- indra/cmake/Variables.cmake | 1 + indra/newview/CMakeLists.txt | 15 + indra/tools/vstool/DispatchUtility.cs | 271 +++++++++++++ indra/tools/vstool/README.txt | 9 + indra/tools/vstool/VSTool.csproj | 98 +++++ indra/tools/vstool/VSTool.exe | Bin 0 -> 24576 bytes indra/tools/vstool/VSTool.sln | 19 + indra/tools/vstool/app.config | 3 + indra/tools/vstool/main.cs | 729 ++++++++++++++++++++++++++++++++++ 9 files changed, 1145 insertions(+) create mode 100644 indra/tools/vstool/DispatchUtility.cs create mode 100644 indra/tools/vstool/README.txt create mode 100755 indra/tools/vstool/VSTool.csproj create mode 100755 indra/tools/vstool/VSTool.exe create mode 100755 indra/tools/vstool/VSTool.sln create mode 100644 indra/tools/vstool/app.config create mode 100755 indra/tools/vstool/main.cs (limited to 'indra') diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 8292a0c63d..63e296b556 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -164,6 +164,7 @@ set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside") set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Linden-supplied prebuilt libraries.") +set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.") set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 586a56b49a..dce0ea73cd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1799,6 +1799,21 @@ if (WINDOWS) windows-crash-logger ) + # sets the 'working directory' for debugging from visual studio. + if (NOT UNATTENDED) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe + ARGS + --solution + ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln + --workingdir + ${VIEWER_BINARY_NAME} + "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." + ) + endif (NOT UNATTENDED) + if (PACKAGE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2 diff --git a/indra/tools/vstool/DispatchUtility.cs b/indra/tools/vstool/DispatchUtility.cs new file mode 100644 index 0000000000..6056ac55a1 --- /dev/null +++ b/indra/tools/vstool/DispatchUtility.cs @@ -0,0 +1,271 @@ +#region Using Directives + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Security.Permissions; + +#endregion + +namespace TestDispatchUtility +{ + /// + /// Provides helper methods for working with COM IDispatch objects that have a registered type library. + /// + public static class DispatchUtility + { + #region Private Constants + + private const int S_OK = 0; //From WinError.h + private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800 + + #endregion + + #region Public Methods + + /// + /// Gets whether the specified object implements IDispatch. + /// + /// An object to check. + /// True if the object implements IDispatch. False otherwise. + public static bool ImplementsIDispatch(object obj) + { + bool result = obj is IDispatchInfo; + return result; + } + + /// + /// Gets a Type that can be used with reflection. + /// + /// An object that implements IDispatch. + /// Whether an exception should be thrown if a Type can't be obtained. + /// A .NET Type that can be used with reflection. + /// If doesn't implement IDispatch. + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] + public static Type GetType(object obj, bool throwIfNotFound) + { + RequireReference(obj, "obj"); + Type result = GetType((IDispatchInfo)obj, throwIfNotFound); + return result; + } + + /// + /// Tries to get the DISPID for the requested member name. + /// + /// An object that implements IDispatch. + /// The name of a member to lookup. + /// If the method returns true, this holds the DISPID on output. + /// If the method returns false, this value should be ignored. + /// True if the member was found and resolved to a DISPID. False otherwise. + /// If doesn't implement IDispatch. + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] + public static bool TryGetDispId(object obj, string name, out int dispId) + { + RequireReference(obj, "obj"); + bool result = TryGetDispId((IDispatchInfo)obj, name, out dispId); + return result; + } + + /// + /// Invokes a member by DISPID. + /// + /// An object that implements IDispatch. + /// The DISPID of a member. This can be obtained using + /// . + /// The arguments to pass to the member. + /// The member's return value. + /// + /// This can invoke a method or a property get accessor. + /// + public static object Invoke(object obj, int dispId, object[] args) + { + string memberName = "[DispId=" + dispId + "]"; + object result = Invoke(obj, memberName, args); + return result; + } + + /// + /// Invokes a member by name. + /// + /// An object. + /// The name of the member to invoke. + /// The arguments to pass to the member. + /// The member's return value. + /// + /// This can invoke a method or a property get accessor. + /// + public static object Invoke(object obj, string memberName, object[] args) + { + RequireReference(obj, "obj"); + Type type = obj.GetType(); + object result = type.InvokeMember(memberName, BindingFlags.InvokeMethod | BindingFlags.GetProperty, + null, obj, args, null); + return result; + } + + #endregion + + #region Private Methods + + /// + /// Requires that the value is non-null. + /// + /// The type of the value. + /// The value to check. + /// The name of the value. + private static void RequireReference(T value, string name) where T : class + { + if (value == null) + { + throw new ArgumentNullException(name); + } + } + + /// + /// Gets a Type that can be used with reflection. + /// + /// An object that implements IDispatch. + /// Whether an exception should be thrown if a Type can't be obtained. + /// A .NET Type that can be used with reflection. + private static Type GetType(IDispatchInfo dispatch, bool throwIfNotFound) + { + RequireReference(dispatch, "dispatch"); + + Type result = null; + int typeInfoCount; + int hr = dispatch.GetTypeInfoCount(out typeInfoCount); + if (hr == S_OK && typeInfoCount > 0) + { + // Type info isn't usually culture-aware for IDispatch, so we might as well pass + // the default locale instead of looking up the current thread's LCID each time + // (via CultureInfo.CurrentCulture.LCID). + dispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out result); + } + + if (result == null && throwIfNotFound) + { + // If the GetTypeInfoCount called failed, throw an exception for that. + Marshal.ThrowExceptionForHR(hr); + + // Otherwise, throw the same exception that Type.GetType would throw. + throw new TypeLoadException(); + } + + return result; + } + + /// + /// Tries to get the DISPID for the requested member name. + /// + /// An object that implements IDispatch. + /// The name of a member to lookup. + /// If the method returns true, this holds the DISPID on output. + /// If the method returns false, this value should be ignored. + /// True if the member was found and resolved to a DISPID. False otherwise. + private static bool TryGetDispId(IDispatchInfo dispatch, string name, out int dispId) + { + RequireReference(dispatch, "dispatch"); + RequireReference(name, "name"); + + bool result = false; + + // Members names aren't usually culture-aware for IDispatch, so we might as well + // pass the default locale instead of looking up the current thread's LCID each time + // (via CultureInfo.CurrentCulture.LCID). + Guid iidNull = Guid.Empty; + int hr = dispatch.GetDispId(ref iidNull, ref name, 1, LOCALE_SYSTEM_DEFAULT, out dispId); + + const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); //From WinError.h + const int DISPID_UNKNOWN = -1; //From OAIdl.idl + if (hr == S_OK) + { + result = true; + } + else if (hr == DISP_E_UNKNOWNNAME && dispId == DISPID_UNKNOWN) + { + // This is the only supported "error" case because it means IDispatch + // is saying it doesn't know the member we asked about. + result = false; + } + else + { + // The other documented result codes are all errors. + Marshal.ThrowExceptionForHR(hr); + } + + return result; + } + + #endregion + + #region Private Interfaces + + /// + /// A partial declaration of IDispatch used to lookup Type information and DISPIDs. + /// + /// + /// This interface only declares the first three methods of IDispatch. It omits the + /// fourth method (Invoke) because there are already plenty of ways to do dynamic + /// invocation in .NET. But the first three methods provide dynamic type metadata + /// discovery, which .NET doesn't provide normally if you have a System.__ComObject + /// RCW instead of a strongly-typed RCW. + /// + /// Note: The original declaration of IDispatch is in OAIdl.idl. + /// + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("00020400-0000-0000-C000-000000000046")] + private interface IDispatchInfo + { + /// + /// Gets the number of Types that the object provides (0 or 1). + /// + /// Returns 0 or 1 for the number of Types provided by . + /// + /// http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85) + /// + [PreserveSig] + int GetTypeInfoCount(out int typeInfoCount); + + /// + /// Gets the Type information for an object if returned 1. + /// + /// Must be 0. + /// Typically, LOCALE_SYSTEM_DEFAULT (2048). + /// Returns the object's Type information. + /// + /// http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85) + /// + void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, + MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo); + + /// + /// Gets the DISPID of the specified member name. + /// + /// Must be IID_NULL. Pass a copy of Guid.Empty. + /// The name of the member to look up. + /// Must be 1. + /// Typically, LOCALE_SYSTEM_DEFAULT (2048). + /// If a member with the requested + /// is found, this returns its DISPID and the method's return value is 0. + /// If the method returns a non-zero value, then this parameter's output value is + /// undefined. + /// Zero for success. Non-zero for failure. + /// + /// http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85) + /// + [PreserveSig] + int GetDispId(ref Guid riid, ref string name, int nameCount, int lcid, out int dispId); + + // NOTE: The real IDispatch also has an Invoke method next, but we don't need it. + // We can invoke methods using .NET's Type.InvokeMember method with the special + // [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo + // and invoke methods on that through reflection. + // Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx + } + + #endregion + } +} diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt new file mode 100644 index 0000000000..e419180031 --- /dev/null +++ b/indra/tools/vstool/README.txt @@ -0,0 +1,9 @@ +VSTool is a command line utility to manipulate VisualStudio settings. + +The windows cmake project configuration uses VSTool.exe + +A handy upgrade: + figure out how to make cmake build this csharp app + - or write the app using script (jscript?!?) so it doesn't need to be built. + + diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj new file mode 100755 index 0000000000..7f431e85c7 --- /dev/null +++ b/indra/tools/vstool/VSTool.csproj @@ -0,0 +1,98 @@ + + + + Local + 8.0.50727 + 2.0 + {96943E2D-1373-4617-A117-D0F997A94919} + Debug + AnyCPU + + + + + VSTool + + + JScript + Grid + IE50 + false + Exe + VSTool + Always + VSTool.VSToolMain + + + + + v2.0 + 2.0 + + + .\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + .\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + System.Data + + + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/indra/tools/vstool/VSTool.exe b/indra/tools/vstool/VSTool.exe new file mode 100755 index 0000000000..854290b90a Binary files /dev/null and b/indra/tools/vstool/VSTool.exe differ diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln new file mode 100755 index 0000000000..21e3d75971 --- /dev/null +++ b/indra/tools/vstool/VSTool.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/indra/tools/vstool/app.config b/indra/tools/vstool/app.config new file mode 100644 index 0000000000..8494f728ff --- /dev/null +++ b/indra/tools/vstool/app.config @@ -0,0 +1,3 @@ + + + diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs new file mode 100755 index 0000000000..ef2e582b90 --- /dev/null +++ b/indra/tools/vstool/main.cs @@ -0,0 +1,729 @@ +// Code about getting running instances visual studio +// was borrowed from +// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.CSharp; + +namespace VSTool +{ + // The MessageFilter class comes from: + // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx + // It allows vstool to get timing error messages from + // visualstudio and handle them. + public class MessageFilter : IOleMessageFilter + { + // + // Class containing the IOleMessageFilter + // thread error-handling functions. + + // Start the filter. + public static void Register() + { + IOleMessageFilter newFilter = new MessageFilter(); + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(newFilter, out oldFilter); + } + + // Done with the filter, close it. + public static void Revoke() + { + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(null, out oldFilter); + } + + // + // IOleMessageFilter functions. + // Handle incoming thread requests. + int IOleMessageFilter.HandleInComingCall(int dwCallType, + System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr + lpInterfaceInfo) + { + //Return the flag SERVERCALL_ISHANDLED. + return 0; + } + + // Thread call was rejected, so try again. + int IOleMessageFilter.RetryRejectedCall(System.IntPtr + hTaskCallee, int dwTickCount, int dwRejectType) + { + if (dwRejectType == 2) + // flag = SERVERCALL_RETRYLATER. + { + // Retry the thread call immediately if return >=0 & + // <100. + return 99; + } + // Too busy; cancel call. + return -1; + } + + int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, + int dwTickCount, int dwPendingType) + { + //Return the flag PENDINGMSG_WAITDEFPROCESS. + return 2; + } + + // Implement the IOleMessageFilter interface. + [DllImport("Ole32.dll")] + private static extern int + CoRegisterMessageFilter(IOleMessageFilter newFilter, out + IOleMessageFilter oldFilter); + } + + [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + interface IOleMessageFilter + { + [PreserveSig] + int HandleInComingCall( + int dwCallType, + IntPtr hTaskCaller, + int dwTickCount, + IntPtr lpInterfaceInfo); + + [PreserveSig] + int RetryRejectedCall( + IntPtr hTaskCallee, + int dwTickCount, + int dwRejectType); + + [PreserveSig] + int MessagePending( + IntPtr hTaskCallee, + int dwTickCount, + int dwPendingType); + } + + class ViaCOM + { + public static object GetProperty(object from_obj, string prop_name) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.GetProperty, null, + from_obj, + null); + } + catch (Exception e) + { + Console.WriteLine("Error getting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object SetProperty(object from_obj, string prop_name, object new_value) + { + try + { + object[] args = { new_value }; + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.SetProperty, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error setting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object CallMethod(object from_obj, string method_name, params object[] args) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + method_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.InvokeMethod, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error calling method \"{0}\"", method_name); + Console.WriteLine(e.Message); + throw e; + } + } + }; + + /// + /// The main entry point class for VSTool. + /// + class VSToolMain + { + #region Interop imports + [DllImport("ole32.dll")] + public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); + + [DllImport("ole32.dll")] + public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); + #endregion + + static System.Boolean ignore_case = true; + + static string solution_name = null; + static bool use_new_vs = false; + static Hashtable projectDict = new Hashtable(); + static string startup_project = null; + static string config = null; + + static object dte = null; + static object solution = null; + + /// + /// The main entry point for the application. + /// + [STAThread] + static int Main(string[] args) + { + int retVal = 0; + bool need_save = false; + + try + { + parse_command_line(args); + + Console.WriteLine("Editing solution: {0}", solution_name); + + bool found_open_solution = GetDTEAndSolution(); + + if (dte == null || solution == null) + { + retVal = 1; + } + else + { + MessageFilter.Register(); + + // Walk through all of the projects in the solution + // and list the type of each project. + foreach (DictionaryEntry p in projectDict) + { + string project_name = (string)p.Key; + string working_dir = (string)p.Value; + if (SetProjectWorkingDir(solution, project_name, working_dir)) + { + need_save = true; + } + } + + if (config != null) + { + need_save = SetActiveConfig(config); + } + + if (startup_project != null) + { + need_save = SetStartupProject(startup_project); + } + + if (need_save) + { + if (found_open_solution == false) + { + ViaCOM.CallMethod(solution, "Close", null); + } + } + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + retVal = 1; + } + finally + { + if (solution != null) + { + Marshal.ReleaseComObject(solution); + solution = null; + } + + if (dte != null) + { + Marshal.ReleaseComObject(dte); + dte = null; + } + + MessageFilter.Revoke(); + } + return retVal; + } + + public static bool parse_command_line(string[] args) + { + string options_desc = + "--solution : MSVC solution name. (required)\n" + + "--use_new_vs : Ignore running versions of visual studio.\n" + + "--workingdir : Set working dir of a VC project.\n" + + "--config : Set the active config for the solution.\n" + + "--startup : Set the startup project for the solution.\n"; + + try + { + // Command line param parsing loop. + int i = 0; + for (; i < args.Length; ++i) + { + if ("--solution" == args[i]) + { + if (solution_name != null) + { + throw new ApplicationException("Found second --solution option"); + } + solution_name = args[++i]; + } + else if ("--use_new_vs" == args[i]) + { + use_new_vs = true; + } + + else if ("--workingdir" == args[i]) + { + string project_name = args[++i]; + string working_dir = args[++i]; + projectDict.Add(project_name, working_dir); + } + else if ("--config" == args[i]) + { + if (config != null) + { + throw new ApplicationException("Found second --config option"); + } + config = args[++i]; + } + else if ("--startup" == args[i]) + { + if (startup_project != null) + { + throw new ApplicationException("Found second --startup option"); + } + startup_project = args[++i]; + } + else + { + throw new ApplicationException("Found unrecognized token on command line: " + args[i]); + } + } + + if (solution_name == null) + { + throw new ApplicationException("The --solution option is required."); + } + } + catch(ApplicationException e) + { + + Console.WriteLine("Oops! " + e.Message); + Console.Write("Command line:"); + foreach (string arg in args) + { + Console.Write(" " + arg); + } + Console.Write("\n\n"); + Console.WriteLine("VSTool command line usage"); + Console.Write(options_desc); + throw e; + } + return true; + } + + public static bool GetDTEAndSolution() + { + bool found_open_solution = true; + + Console.WriteLine("Looking for existing VisualStudio instance..."); + + // Get an instance of the currently running Visual Studio .NET IDE. + // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1"); + string full_solution_name = System.IO.Path.GetFullPath(solution_name); + if (false == use_new_vs) + { + dte = GetIDEInstance(full_solution_name); + } + + if (dte == null) + { + try + { + Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance..."); + Console.WriteLine(" Reading .sln file version..."); + string version = GetSolutionVersion(full_solution_name); + + Console.WriteLine(" Using version: {0}...", version); + string progid = GetVSProgID(version); + + Type objType = Type.GetTypeFromProgID(progid); + dte = System.Activator.CreateInstance(objType); + Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name); + + solution = ViaCOM.GetProperty(dte, "Solution"); + object[] openArgs = { full_solution_name }; + ViaCOM.CallMethod(solution, "Open", openArgs); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine("Quitting do to error opening: {0}", full_solution_name); + solution = null; + dte = null; + return found_open_solution; + } + found_open_solution = false; + } + + if (solution == null) + { + solution = ViaCOM.GetProperty(dte, "Solution"); + } + + return found_open_solution; + } + + /// + /// Get the DTE object for the instance of Visual Studio IDE that has + /// the specified solution open. + /// + /// The absolute filename of the solution + /// Corresponding DTE object or null if no such IDE is running + public static object GetIDEInstance( string solutionFile ) + { + Hashtable runningInstances = GetIDEInstances( true ); + IDictionaryEnumerator enumerator = runningInstances.GetEnumerator(); + + while ( enumerator.MoveNext() ) + { + try + { + object ide = enumerator.Value; + if (ide != null) + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case)) + { + return ide; + } + } + } + catch{} + } + + return null; + } + + /// + /// Get a table of the currently running instances of the Visual Studio .NET IDE. + /// + /// Only return instances that have opened a solution + /// A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object + public static Hashtable GetIDEInstances( bool openSolutionsOnly ) + { + Hashtable runningIDEInstances = new Hashtable(); + Hashtable runningObjects = GetRunningObjectTable(); + + IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); + while ( rotEnumerator.MoveNext() ) + { + string candidateName = (string) rotEnumerator.Key; + if (!candidateName.StartsWith("!VisualStudio.DTE")) + continue; + + object ide = rotEnumerator.Value; + if (ide == null) + continue; + + if (openSolutionsOnly) + { + try + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName"); + if (solutionFile != String.Empty) + { + runningIDEInstances[ candidateName ] = ide; + } + } + catch {} + } + else + { + runningIDEInstances[ candidateName ] = ide; + } + } + return runningIDEInstances; + } + + /// + /// Get a snapshot of the running object table (ROT). + /// + /// A hashtable mapping the name of the object in the ROT to the corresponding object + [STAThread] + public static Hashtable GetRunningObjectTable() + { + Hashtable result = new Hashtable(); + + int numFetched = 0; + IRunningObjectTable runningObjectTable; + IEnumMoniker monikerEnumerator; + IMoniker[] monikers = new IMoniker[1]; + + GetRunningObjectTable(0, out runningObjectTable); + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0) + { + IBindCtx ctx; + CreateBindCtx(0, out ctx); + + string runningObjectName; + monikers[0].GetDisplayName(ctx, null, out runningObjectName); + + object runningObjectVal; + runningObjectTable.GetObject( monikers[0], out runningObjectVal); + + result[ runningObjectName ] = runningObjectVal; + } + + return result; + } + + public static string GetSolutionVersion(string solutionFullFileName) + { + string version; + System.IO.StreamReader solutionStreamReader = null; + string firstLine; + string format; + + try + { + solutionStreamReader = new System.IO.StreamReader(solutionFullFileName); + do + { + firstLine = solutionStreamReader.ReadLine(); + } + while (firstLine == ""); + + format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim(); + + switch(format) + { + case "7.00": + version = "VC70"; + break; + + case "8.00": + version = "VC71"; + break; + + case "9.00": + version = "VC80"; + break; + + case "10.00": + version = "VC90"; + break; + + case "11.00": + version = "VC100"; + break; + + case "12.00": + version = "VC120"; + break; + + default: + throw new ApplicationException("Unknown .sln version: " + format); + } + } + finally + { + if(solutionStreamReader != null) + { + solutionStreamReader.Close(); + } + } + + return version; + } + + public static string GetVSProgID(string version) + { + string progid = null; + switch(version) + { + case "VC70": + progid = "VisualStudio.DTE.7"; + break; + + case "VC71": + progid = "VisualStudio.DTE.7.1"; + break; + + case "VC80": + progid = "VisualStudio.DTE.8.0"; + break; + + case "VC90": + progid = "VisualStudio.DTE.9.0"; + break; + + case "VC100": + progid = "VisualStudio.DTE.10.0"; + break; + + case "VC120": + progid = "VisualStudio.DTE.12.0"; + break; + + default: + throw new ApplicationException("Can't handle VS version: " + version); + } + + return progid; + } + + public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir) + { + bool made_change = false; + Console.WriteLine("Looking for project {0}...", project_name); + try + { + object prjs = ViaCOM.GetProperty(sol, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for(int i = 1; i <= (int)count; ++i) + { + object[] prjItemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs); + string name = (string)ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare(name, project_name, ignore_case)) + { + Console.WriteLine("Found project: {0}", project_name); + Console.WriteLine("Setting working directory"); + + string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName"); + Console.WriteLine(full_project_name); + + // *NOTE:Mani Thanks to incompatibilities between different versions of the + // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to + // the VCProjectEngine types from a different version than the one built + // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built + // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, + // without the type casting. Its tedious code, but it seems to work. + + // oCfgs should be assigned to a 'Project.Configurations' collection. + object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations"); + + // oCount will be assigned to the number of configs present in oCfgs. + object oCount = ViaCOM.GetProperty(oCfgs, "Count"); + + for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex) + { + object[] itemArgs = {(object)cfgIndex}; + object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs); + object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings"); + ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir); + } + + break; + } + } + made_change = true; + } + catch( Exception e ) + { + Console.WriteLine(e.Message); + Console.WriteLine("Failed to set working dir for project, {0}.", project_name); + } + + return made_change; + } + + public static bool SetStartupProject(string startup_project) + { + bool result = false; + try + { + // You need the 'unique name of the project to set StartupProjects. + // find the project by generic name. + Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project); + object prjs = ViaCOM.GetProperty(solution, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for (int i = 1; i <= (int)count; ++i) + { + object[] itemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs); + object prjName = ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare((string)prjName, startup_project, ignore_case)) + { + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName")); + Console.WriteLine(" Success!"); + result = true; + break; + } + } + + if (result == false) + { + Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project); + } + } + catch (Exception e) + { + Console.WriteLine(" Failed to set the startup project!"); + Console.WriteLine(e.Message); + } + return result; + } + + public static bool SetActiveConfig(string config) + { + bool result = false; + try + { + Console.WriteLine("Trying to set active config to \"{0}\"", config); + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations"); + object[] itemArgs = { (object)config }; + object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs); + ViaCOM.CallMethod(solCfg, "Activate", null); + Console.WriteLine(" Success!"); + result = true; + } + catch (Exception e) + { + Console.WriteLine(" Failed to set \"{0}\" as the active config.", config); + Console.WriteLine(e.Message); + } + return result; + } + } +} -- cgit v1.2.3 From 0f061689914d1d73272d373c877d1656933ae501 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 17 Aug 2016 20:35:00 +0300 Subject: MAINT-6655 Group inspector doesn't support default icon. --- indra/newview/llgroupiconctrl.cpp | 20 ++++++++++---------- indra/newview/llgroupiconctrl.h | 8 +++++++- indra/newview/llinspectgroup.cpp | 3 ++- indra/newview/lltexturectrl.cpp | 2 +- indra/newview/skins/default/xui/en/inspect_group.xml | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 271dd44c1f..7c2a3cad43 100644 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -74,9 +74,16 @@ LLGroupIconCtrl::~LLGroupIconCtrl() LLGroupMgr::getInstance()->removeObserver(this); } -void LLGroupIconCtrl::setIconId(const LLSD& value) +void LLGroupIconCtrl::setIconId(const LLUUID& icon_id) { - LLIconCtrl::setValue(value); + if (icon_id.notNull()) + { + LLIconCtrl::setValue(icon_id); + } + else + { + LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI); + } } void LLGroupIconCtrl::setValue(const LLSD& value) @@ -122,14 +129,7 @@ bool LLGroupIconCtrl::updateFromCache() LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId); if (!group_data) return false; - if (group_data->mInsigniaID.notNull()) - { - LLIconCtrl::setValue(group_data->mInsigniaID); - } - else - { - LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI); - } + setIconId(group_data->mInsigniaID); if (mDrawTooltip && !group_data->mName.empty()) { diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h index f8b22cf581..43e384d3e2 100644 --- a/indra/newview/llgroupiconctrl.h +++ b/indra/newview/llgroupiconctrl.h @@ -66,7 +66,13 @@ public: */ virtual void setValue(const LLSD& value); - void setIconId(const LLSD& value); + /** + * Sets icon_id as icon value directly. Avoids LLGroupMgr cache checks for group id + * Uses default icon in case id is null. + * + * @params icon_id - it is processed as icon id, default image will be used in case id is null. + */ + void setIconId(const LLUUID& icon_id); // LLGroupMgrObserver observer trigger virtual void changed(LLGroupChange gc); diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp index 8e91af321e..0c5a91e48a 100644 --- a/indra/newview/llinspectgroup.cpp +++ b/indra/newview/llinspectgroup.cpp @@ -233,7 +233,8 @@ void LLInspectGroup::processGroupData() getChild("group_details")->setValue( LLSD(data->mCharter) ); - getChild("group_icon")->setValue( LLSD(data->mInsigniaID) ); + // LLGroupIconCtrl + getChild("group_icon")->setValue(LLSD(mGroupID)); std::string cost; bool is_member = LLGroupActions::isInGroup(mGroupID); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index e5aa740a33..980810835e 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1393,7 +1393,7 @@ void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) void LLTextureCtrl::setImageAssetName(const std::string& name) { - LLPointer imagep = LLUI::getUIImage(name, LLGLTexture::BOOST_PREVIEW); + LLPointer imagep = LLUI::getUIImage(name); if(imagep) { LLViewerFetchedTexture* pTexture = dynamic_cast(imagep->getImage().get()); diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml index 324ff3eabd..a69585074c 100644 --- a/indra/newview/skins/default/xui/en/inspect_group.xml +++ b/indra/newview/skins/default/xui/en/inspect_group.xml @@ -66,7 +66,7 @@ Fear the moose! Fear it! And the mongoose too! width="220"> L$123 to join - Date: Tue, 16 Aug 2016 17:48:52 +0300 Subject: MAINT-6637 DebugAvatarAppearanceMessage incorrectly reports all avatars received COF version as -1 --- indra/newview/llvoavatar.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index aebc066507..f79249d6fa 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7392,16 +7392,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // No backsies zone - if we get here, the message should be valid and usable, will be processed. LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; - if (isSelf()) - { - // Note: - // locally the COF is maintained via LLInventoryModel::accountForUpdate - // which is called from various places. This should match the simhost's - // idea of what the COF version is. AIS however maintains its own version - // of the COF that should be considered canonical. - mLastUpdateReceivedCOFVersion = thisAppearanceVersion; - } - + // Note: + // locally the COF is maintained via LLInventoryModel::accountForUpdate + // which is called from various places. This should match the simhost's + // idea of what the COF version is. AIS however maintains its own version + // of the COF that should be considered canonical. + mLastUpdateReceivedCOFVersion = thisAppearanceVersion; + if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE)) { updateVisualComplexity(); -- cgit v1.2.3 From 7104ededb5f224839a6c8d276a3e578ef570ca94 Mon Sep 17 00:00:00 2001 From: eli Date: Tue, 16 Aug 2016 17:47:49 -0700 Subject: FIX INTL-224 Viewer Set45 translation for bento-box in 9 languages --- .../de/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/de/menu_attachment_other.xml | 1 + .../skins/default/xui/de/menu_attachment_self.xml | 1 + .../skins/default/xui/de/menu_avatar_other.xml | 1 + .../skins/default/xui/de/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/de/menu_viewer.xml | 2 +- .../newview/skins/default/xui/de/notifications.xml | 44 +++++--- .../default/xui/de/panel_preferences_alerts.xml | 3 +- .../default/xui/de/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/de/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/de/strings.xml | 113 ++++++++++++++++++- .../es/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/es/menu_attachment_other.xml | 1 + .../skins/default/xui/es/menu_attachment_self.xml | 1 + .../skins/default/xui/es/menu_avatar_other.xml | 1 + .../skins/default/xui/es/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/es/menu_viewer.xml | 1 + .../newview/skins/default/xui/es/notifications.xml | 46 +++++--- .../default/xui/es/panel_preferences_alerts.xml | 3 +- .../default/xui/es/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/es/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/es/strings.xml | 115 +++++++++++++++++++- .../fr/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/fr/menu_attachment_other.xml | 1 + .../skins/default/xui/fr/menu_attachment_self.xml | 1 + .../skins/default/xui/fr/menu_avatar_other.xml | 1 + .../skins/default/xui/fr/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/fr/menu_viewer.xml | 2 +- .../newview/skins/default/xui/fr/notifications.xml | 48 ++++++--- .../default/xui/fr/panel_preferences_alerts.xml | 3 +- .../default/xui/fr/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/fr/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/fr/strings.xml | 113 ++++++++++++++++++- .../it/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/it/menu_attachment_other.xml | 1 + .../skins/default/xui/it/menu_attachment_self.xml | 1 + .../skins/default/xui/it/menu_avatar_other.xml | 1 + .../skins/default/xui/it/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/it/menu_viewer.xml | 2 +- .../newview/skins/default/xui/it/notifications.xml | 44 +++++--- .../default/xui/it/panel_preferences_alerts.xml | 3 +- .../default/xui/it/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/it/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/it/strings.xml | 113 ++++++++++++++++++- .../ja/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/ja/menu_attachment_other.xml | 1 + .../skins/default/xui/ja/menu_attachment_self.xml | 1 + .../skins/default/xui/ja/menu_avatar_other.xml | 1 + .../skins/default/xui/ja/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/ja/menu_viewer.xml | 2 +- .../newview/skins/default/xui/ja/notifications.xml | 46 +++++--- .../default/xui/ja/panel_preferences_alerts.xml | 3 +- .../default/xui/ja/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/ja/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/ja/strings.xml | 120 +++++++++++++++++++-- .../pt/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/pt/menu_attachment_other.xml | 1 + .../skins/default/xui/pt/menu_attachment_self.xml | 1 + .../skins/default/xui/pt/menu_avatar_other.xml | 1 + .../skins/default/xui/pt/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/pt/menu_viewer.xml | 2 +- .../newview/skins/default/xui/pt/notifications.xml | 46 +++++--- .../default/xui/pt/panel_preferences_alerts.xml | 3 +- .../default/xui/pt/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/pt/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/pt/strings.xml | 115 +++++++++++++++++++- .../skins/default/xui/ru/menu_attachment_other.xml | 1 + .../skins/default/xui/ru/menu_attachment_self.xml | 1 + .../skins/default/xui/ru/menu_avatar_other.xml | 1 + .../skins/default/xui/ru/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/ru/menu_viewer.xml | 2 +- .../newview/skins/default/xui/ru/notifications.xml | 44 +++++--- .../default/xui/ru/panel_preferences_alerts.xml | 3 +- .../default/xui/ru/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/ru/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/ru/strings.xml | 111 +++++++++++++++++-- .../tr/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/tr/menu_attachment_other.xml | 1 + .../skins/default/xui/tr/menu_attachment_self.xml | 1 + .../skins/default/xui/tr/menu_avatar_other.xml | 1 + .../skins/default/xui/tr/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/tr/menu_viewer.xml | 2 +- .../newview/skins/default/xui/tr/notifications.xml | 46 +++++--- .../default/xui/tr/panel_preferences_alerts.xml | 3 +- .../default/xui/tr/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/tr/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/tr/strings.xml | 119 ++++++++++++++++++-- .../zh/floater_preferences_graphics_advanced.xml | 2 +- .../skins/default/xui/zh/menu_attachment_other.xml | 1 + .../skins/default/xui/zh/menu_attachment_self.xml | 1 + .../skins/default/xui/zh/menu_avatar_other.xml | 1 + .../skins/default/xui/zh/menu_avatar_self.xml | 1 + indra/newview/skins/default/xui/zh/menu_viewer.xml | 2 +- .../newview/skins/default/xui/zh/notifications.xml | 48 ++++++--- .../default/xui/zh/panel_preferences_alerts.xml | 3 +- .../default/xui/zh/panel_preferences_graphics1.xml | 5 + .../skins/default/xui/zh/panel_sound_devices.xml | 4 +- indra/newview/skins/default/xui/zh/strings.xml | 113 ++++++++++++++++++- 98 files changed, 1389 insertions(+), 232 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml index 2c141f616f..65a7e255f9 100644 --- a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml @@ -15,7 +15,7 @@ Avatar - + 0 diff --git a/indra/newview/skins/default/xui/de/menu_attachment_other.xml b/indra/newview/skins/default/xui/de/menu_attachment_other.xml index ddb1e7b0b1..ba1b36db06 100644 --- a/indra/newview/skins/default/xui/de/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/de/menu_attachment_other.xml @@ -6,6 +6,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_attachment_self.xml b/indra/newview/skins/default/xui/de/menu_attachment_self.xml index e0f37b28af..cd24e6ad3f 100644 --- a/indra/newview/skins/default/xui/de/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/de/menu_attachment_self.xml @@ -9,6 +9,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_avatar_other.xml b/indra/newview/skins/default/xui/de/menu_avatar_other.xml index 7242ba1495..447655cde7 100644 --- a/indra/newview/skins/default/xui/de/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/de/menu_avatar_other.xml @@ -6,6 +6,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_avatar_self.xml b/indra/newview/skins/default/xui/de/menu_avatar_self.xml index b53f8cd6af..f4a3cc17b8 100644 --- a/indra/newview/skins/default/xui/de/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/de/menu_avatar_self.xml @@ -26,6 +26,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index d83a6071f6..319162db34 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -22,7 +22,6 @@ - @@ -415,6 +414,7 @@ + diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 6fcd025a94..0af00ab705 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -487,6 +487,9 @@ Der Outfit-Ordner enthält keine Kleidung, Körperteile oder Anhänge. Sie können das Objekt nicht anziehen, weil es noch nicht geladen wurde. Warten Sie kurz und versuchen Sie es dann noch einmal. + + Bitte geben Sie zur Anmeldung Ihr Kennwort ein. + Sue haben ein Feld leer gelassen. Sie müssen den Benutzernamen Ihres Avatars eingeben. @@ -555,6 +558,9 @@ Hinweis: Der Cache wird dabei gelöscht/geleert. Die Port-Einstellungen werden nach einem Neustart von [APP_NAME] wirksam. + + Die Debug-Einstellung tritt nach Neustart von [APP_NAME] in Kraft. + Die neue Benutzeroberfläche wird nach einem Neustart von [APP_NAME] angezeigt. @@ -1380,12 +1386,13 @@ Sie können [SECOND_LIFE] normal verwenden. Andere Benutzer können Sie korrekt - - Ihre [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 visuelle Komplexität] ist [AGENT_COMPLEXITY]. + + Ihre [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 Avatarkomplexität] ist [AGENT_COMPLEXITY]. [OVERLIMIT_MSG] + - Ihre [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 visuelle Komplexität] ist [AGENT_COMPLEXITY]. + Ihre [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 Avatarkomplexität] ist [AGENT_COMPLEXITY]. Installation von [APP_NAME] vollständig abgeschlossen. @@ -1501,6 +1508,10 @@ Ersetzen Sie die Textur [TEXTURE_NUM] mit einer Bilddatei von maximal 512x512 un Möchten Sie das aktuelle Terrain formen, es zum Mittelpunkt der oberen und unteren Terraingrenzen und zum Standard des „Zurücksetzen“-Tools machen? + + Sie sind dabei, für Höhenbereiche untere Werte anzugeben, die größer sind als die oberen Werte. Fortfahren? + + Es sind maximal [MAX_AGENTS] zulässige Einwohner erlaubt. @@ -1735,14 +1746,6 @@ Diese Gruppe verlassen? Sie können die Gruppe nicht verlassen, da Sie der letzte Besitzer der Gruppe sind. Weisen Sie die Besitzerrolle zuerst einem anderen Mitglied zu. - - Kann Gruppe nicht verlassen: [reason]. - - - - Sie haben die Gruppe „[group_name]“ verlassen. - - Möchten Sie WIRKLICH alle Benutzer aus dem Grid werfen? @@ -2415,6 +2418,10 @@ Möchten Sie den Nicht-stören-Modus deaktivieren, bevor Sie diese Transaktion a Sind Sie sicher, dass Sie den Inhalt Ihres Papierkorbs löschen möchten? + + Ihr Papierkorb läuft über. Dies kann zu Anmeldeproblemen führen. + + Sind Sie sicher, dass Sie Ihren Reise-, Internet- und Suchverlauf löschen möchten? @@ -3272,11 +3279,15 @@ Diese werden für ein paar Sekunden sicherheitshalber gesperrt. Der Anhang wurde gespeichert. - - Fehler beim Speichern der Voreinstellung [NAME]. + + Erscheinungsbild als XML in [PATH] gespeichert - - Fehler beim Löschen der Voreinstellung [NAME]. + + Fehler beim Speichern des Erscheinungsbilds als XML. + icon="notifytip.tga" + name="PresetNotDeleted" + type="notifytip"> +Fehler beim Löschen der Voreinstellung [NAME]. Hilfethema für dieses Element wurde nicht gefunden. @@ -4089,6 +4100,9 @@ Warten Sie kurz und versuchen Sie es noch einmal. Nicht genügend Skriptressourcen verfügbar, um Objekt anzuhängen. + + Der Anhang hat einen nicht vorhandenen Punkt auf dem Avatar angefordert. Der Anhang wurde stattdessen auf der Brust angebracht. + Ablegen von Objekten hier nicht möglich; versuchen Sie es mit dem kostenlosen Testbereich. diff --git a/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml index fcb45e26be..508e87a8b7 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml @@ -3,8 +3,9 @@ Anzeigen: - + + Immer anzeigen: diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml index 06fd22141f..74fb4d0f85 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml @@ -24,10 +24,15 @@ Besser + + + 0 +