From 2dff12433cc5d42acc8a44e0338e49a9f80c6084 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 28 Apr 2011 10:09:11 -0500 Subject: [PATCH 1/9] Avatar Physics innital commit. No edit panel. SavedSettings not plugged in yet. --- indra/newview/CMakeLists.txt | 2 + indra/newview/character/avatar_lad.xml | 693 +++++++++++++++- indra/newview/llagent.cpp | 5 +- indra/newview/llassetconverter.cpp | 2 +- indra/newview/lldriverparam.h | 2 + indra/newview/llfilepicker.cpp | 10 + indra/newview/llfilepicker.h | 1 + indra/newview/llfloatercustomize.cpp | 12 +- indra/newview/llinventoryactions.cpp | 6 +- indra/newview/llinventorybackup.cpp | 2 + indra/newview/llinventorybridge.cpp | 5 + indra/newview/llinventorybridge.h | 2 + indra/newview/llinventoryview.cpp | 3 + indra/newview/llphysicsmotion.cpp | 747 ++++++++++++++++++ indra/newview/llphysicsmotion.h | 124 +++ indra/newview/llpolymesh.cpp | 118 ++- indra/newview/llpolymorph.cpp | 56 +- indra/newview/llpolymorph.h | 1 + indra/newview/llviewermenu.cpp | 9 + indra/newview/llvoavatar.cpp | 15 +- indra/newview/llvoavatar.h | 2 + indra/newview/llwearable.cpp | 3 + indra/newview/llwearable.h | 3 +- indra/newview/rlvhandler.cpp | 2 +- .../default/textures/inv_item_physics.png | Bin 0 -> 539 bytes .../default/xui/en-us/floater_inventory.xml | 4 + .../default/xui/en-us/menu_inventory.xml | 4 + .../skins/default/xui/en-us/menu_pie_self.xml | 5 + .../skins/default/xui/en-us/menu_viewer.xml | 7 +- 29 files changed, 1821 insertions(+), 24 deletions(-) create mode 100644 indra/newview/llphysicsmotion.cpp create mode 100644 indra/newview/llphysicsmotion.h create mode 100644 indra/newview/skins/default/textures/inv_item_physics.png diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index cc73ffc32..bd7a541fc 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -348,6 +348,7 @@ set(viewer_SOURCE_FILES llpanelweb.cpp llparcelselection.cpp llpatchvertexarray.cpp + llphysicsmotion.cpp llpolymesh.cpp llpolymorph.cpp llprefschat.cpp @@ -822,6 +823,7 @@ set(viewer_HEADER_FILES llpanelweb.h llparcelselection.h llpatchvertexarray.h + llphysicsmotion.h llpolymesh.h llpolymorph.h llprefschat.h diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 7c320eceb..b2f3aea4c 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -2923,6 +2923,8 @@ id="40" group="1" name="Male_Head" + wearable="shape" + edit_group="driven" value_min="0" value_max="1"> @@ -3508,6 +3510,8 @@ id="104" group="1" name="Big_Belly_Torso" + wearable="shape" + edit_group="driven" value_min="0" value_max="1"> @@ -3824,6 +3828,8 @@ id="855" group="1" name="Love_Handles" + wearable="shape" + edit_group="driven" value_default="0" value_min="-1" value_max="2"> @@ -3879,6 +3885,8 @@ id="100" group="1" name="Male_Torso" + wearable="shape" + edit_group="driven" label_min="Male_Torso" value_min="0" value_max="1"> @@ -4047,9 +4055,66 @@ - + + + + + + + + + + + + + + + + + + + @@ -4537,15 +4607,62 @@ id="153" group="1" name="Male_Legs" + wearable="shape" + edit_group="driven" value_min="0" value_max="1"> - - + + + + + + + + + + + + + + + + + @@ -4828,6 +4946,8 @@ id="852" group="1" name="skirt_bigbutt" + wearable="skirt" + edit_group="driven" label="bigbutt skirt" label_min="less" label_max="more" @@ -4840,6 +4960,8 @@ id="849" group="1" name="skirt_belly" + wearable="skirt" + edit_group="driven" label="big belly skirt" value_min="0" value_max="1"> @@ -4849,6 +4971,8 @@ @@ -4859,6 +4983,8 @@ id="851" group="1" name="skirt_chubby" + wearable="skirt" + edit_group="driven" label_min="less" label_max="more" value_min="0" @@ -4871,6 +4997,8 @@ id="856" group="1" name="skirt_lovehandles" + wearable="skirt" + edit_group="driven" label_min="less" label_max="more" value_min="-1" @@ -4888,11 +5016,32 @@ id="857" group="1" name="skirt_male" + wearable="skirt" + edit_group="driven" value_min="0" value_max="1"> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 5917d402f..39da9489f 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -7306,7 +7306,8 @@ void LLAgent::createStandardWearables(BOOL female) TRUE, //WT_UNDERPANTS FALSE, //WT_SKIRT FALSE, //WT_ALPHA - FALSE //WT_TATTOO + FALSE, //WT_TATTOO + FALSE, //WT_PHYSICS }; for( S32 i=0; i < WT_COUNT; i++ ) @@ -7918,6 +7919,7 @@ void LLAgent::setWearableOutfit( wearables_to_remove[WT_SKIRT] = remove && gRlvWearableLocks.canRemove(WT_SKIRT); wearables_to_remove[WT_ALPHA] = remove && gRlvWearableLocks.canRemove(WT_ALPHA); wearables_to_remove[WT_TATTOO] = remove && gRlvWearableLocks.canRemove(WT_TATTOO); + wearables_to_remove[WT_PHYSICS] = remove && gRlvWearableLocks.canRemove(WT_PHYSICS); // [/RLVa:KB] S32 count = wearables.count(); @@ -8199,6 +8201,7 @@ void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata ) gAgent.removeWearable( WT_SKIRT ); gAgent.removeWearable( WT_ALPHA ); gAgent.removeWearable( WT_TATTOO ); + gAgent.removeWearable( WT_PHYSICS ); } } diff --git a/indra/newview/llassetconverter.cpp b/indra/newview/llassetconverter.cpp index 53c56a49c..73da5cd26 100644 --- a/indra/newview/llassetconverter.cpp +++ b/indra/newview/llassetconverter.cpp @@ -144,7 +144,7 @@ LLAssetType::EType LLAssetConverter::convert(std::string src_filename, std::stri return LLAssetType::AT_NONE; } } - else if(exten == "eyes" || exten == "gloves" || exten == "hair" || exten == "jacket" || exten == "pants" || exten == "shape" || exten == "shirt" || exten == "shoes" || exten == "skin" || exten == "skirt" || exten == "socks" || exten == "underpants" || exten == "undershirt" || exten == "bodypart" || exten == "clothing") + else if(exten == "eyes" || exten == "gloves" || exten == "hair" || exten == "jacket" || exten == "pants" || exten == "shape" || exten == "shirt" || exten == "shoes" || exten == "skin" || exten == "skirt" || exten == "socks" || exten == "underpants" || exten == "undershirt" || exten == "bodypart" || exten == "clothing" || exten == "physics") { asset_type = LLAssetType::AT_CLOTHING; if(!copyFile(src_filename, filename)) diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index 7bc0c1544..2e53ce563 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -35,6 +35,7 @@ #include "llviewervisualparam.h" +class LLPhysicsMotion; class LLVOAvatar; //----------------------------------------------------------------------------- @@ -78,6 +79,7 @@ protected: class LLDriverParam : public LLViewerVisualParam { + friend class LLPhysicsMotion; // physics motion needs to access driven params directly. public: LLDriverParam(LLVOAvatar *avatarp); ~LLDriverParam(); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8648eef7c..5cea197ca 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -693,6 +693,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) L"Asset Blacklists (*.blacklist)\0*.blacklist\0" \ L"\0"; break; + case FFSAVE_PHYSICS: + if(filename.empty()) + { + wcsncpy( mFilesW,L"untitled.phy", FILENAME_BUFFER_SIZE); + } + mOFN.lpstrDefExt = L"phy"; + mOFN.lpstrFilter = + L"Landmarks (*.phy)\0*.phy\0" \ + L"\0"; + break; // default: return FALSE; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index ea1e61fc2..feba53423 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -139,6 +139,7 @@ public: FFSAVE_LANDMARK = 34, FFSAVE_AO = 35, FFSAVE_BLACKLIST = 36, + FFSAVE_PHYSICS = 37, // }; diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 39d3ce5ab..2cc35f404 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -405,7 +405,14 @@ enum ESubpart { SUBPART_UNDERPANTS, SUBPART_SKIRT, SUBPART_ALPHA, - SUBPART_TATTOO + SUBPART_TATTOO, + SUBPART_PHYSICS_BREASTS_UPDOWN, + SUBPART_PHYSICS_BREASTS_INOUT, + SUBPART_PHYSICS_BREASTS_LEFTRIGHT, + SUBPART_PHYSICS_BELLY_UPDOWN, + SUBPART_PHYSICS_BUTT_UPDOWN, + SUBPART_PHYSICS_BUTT_LEFTRIGHT, + SUBPART_PHYSICS_ADVANCED }; struct LLSubpart @@ -926,6 +933,7 @@ ESubpart LLPanelEditWearable::getDefaultSubpart() case WT_SKIRT: return SUBPART_SKIRT; case WT_ALPHA: return SUBPART_ALPHA; case WT_TATTOO: return SUBPART_TATTOO; + case WT_PHYSICS: return SUBPART_PHYSICS_BELLY_UPDOWN; default: llassert(0); return SUBPART_SHAPE_WHOLE; } @@ -1708,6 +1716,7 @@ LLFloaterCustomize::LLFloaterCustomize() factory_map["Skirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SKIRT) ) ); factory_map["Alpha"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_ALPHA))); factory_map["Tattoo"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_TATTOO))); + factory_map["Physics"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_PHYSICS))); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_customize.xml", &factory_map); } @@ -1741,6 +1750,7 @@ BOOL LLFloaterCustomize::postBuild() childSetTabChangeCallback("customize tab container", "Skirt", onTabChanged, (void*)WT_SKIRT, onTabPrecommit ); childSetTabChangeCallback("customize tab container", "Alpha", onTabChanged, (void*)WT_ALPHA, onTabPrecommit); childSetTabChangeCallback("customize tab container", "Tattoo", onTabChanged, (void*)WT_TATTOO, onTabPrecommit); + childSetTabChangeCallback("customize tab container", "Physics", onTabChanged, (void*)WT_PHYSICS, onTabPrecommit); // Remove underwear panels for teens if (gAgent.isTeen()) diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 4c41ddb66..b770a531d 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -462,7 +462,11 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); LLFolderBridge::createWearable(parent_id, WT_EYES); } - + else if ("physics" == type) + { + LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + LLFolderBridge::createWearable(parent_id, WT_PHYSICS); + } ptr->getRootFolder()->setNeedsAutoRename(TRUE); } diff --git a/indra/newview/llinventorybackup.cpp b/indra/newview/llinventorybackup.cpp index 4ad9e79bb..a5ce38e59 100644 --- a/indra/newview/llinventorybackup.cpp +++ b/indra/newview/llinventorybackup.cpp @@ -209,6 +209,8 @@ LLFilePicker::ESaveFilter LLInventoryBackup::getSaveFilter(LLInventoryItem* item return LLFilePicker::FFSAVE_UNDERPANTS; case WT_UNDERSHIRT: return LLFilePicker::FFSAVE_UNDERSHIRT; + case WT_PHYSICS: + return LLFilePicker::FFSAVE_PHYSICS; default: return LLFilePicker::FFSAVE_ALL; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3ac7342ae..3455caf19 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -186,6 +186,7 @@ std::string ICON_NAME[ICON_NAME_COUNT] = "inv_item_skirt.tga", "inv_item_alpha.tga", "inv_item_tattoo.tga", + "inv_item_physics.png", "inv_item_animation.tga", "inv_item_gesture.tga", @@ -2712,6 +2713,10 @@ void LLFolderBridge::createNewEyes(void* user_data) LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); } +void LLFolderBridge::createNewPhysics(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PHYSICS); +} // static void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index e9f131f68..dcadc2781 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -72,6 +72,7 @@ enum EInventoryIcon CLOTHING_SKIRT_ICON_NAME, CLOTHING_ALPHA_ICON_NAME, CLOTHING_TATTOO_ICON_NAME, + CLOTHING_PHYSICS_ICON_NAME, ANIMATION_ICON_NAME, GESTURE_ICON_NAME, @@ -375,6 +376,7 @@ protected: static void createNewSkin(void* user_data); static void createNewHair(void* user_data); static void createNewEyes(void* user_data); + static void createNewPhysics(void* user_data); BOOL checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& typeToCheck); diff --git a/indra/newview/llinventoryview.cpp b/indra/newview/llinventoryview.cpp index 1e9ce663a..1d89872c9 100644 --- a/indra/newview/llinventoryview.cpp +++ b/indra/newview/llinventoryview.cpp @@ -1521,6 +1521,9 @@ std::string get_item_icon_name(LLAssetType::EType asset_type, case WT_TATTOO: idx = CLOTHING_TATTOO_ICON_NAME; break; + case WT_PHYSICS: + idx = CLOTHING_PHYSICS_ICON_NAME; + break; default: // no-op, go with choice above break; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp new file mode 100644 index 000000000..59434a1f1 --- /dev/null +++ b/indra/newview/llphysicsmotion.cpp @@ -0,0 +1,747 @@ +/** + * @file llphysicsmotion.cpp + * @brief Implementation of LLPhysicsMotion class. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "m3math.h" +#include "v3dmath.h" + +#include "llphysicsmotion.h" +#include "llagent.h" +#include "llcharacter.h" +#include "llviewercontrol.h" +#include "llviewervisualparam.h" +#include "llvoavatar.h" +#include "lldriverparam.h" + +typedef std::map controller_map_t; +typedef std::map default_controller_map_t; + +#define MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION 0.f +#define TIME_ITERATION_STEP 0.1f + +inline F64 llsgn(const F64 a) +{ + if (a >= 0) + return 1; + return -1; +} + +/* + At a high level, this works by setting temporary parameters that are not stored + in the avatar's list of params, and are not conveyed to other users. We accomplish + this by creating some new temporary driven params inside avatar_lad that are then driven + by the actual params that the user sees and sets. For example, in the old system, + the user sets a param called breast bouyancy, which controls the Z value of the breasts. + In our new system, the user still sets the breast bouyancy, but that param is redefined + as a driver param so that affects a new temporary driven param that the bounce is applied + to. +*/ + +class LLPhysicsMotion +{ +public: + /* + param_driver_name: The param that controls the params that are being affected by the physics. + joint_name: The joint that the body part is attached to. The joint is + used to determine the orientation (rotation) of the body part. + + character: The avatar that this physics affects. + + motion_direction_vec: The direction (in world coordinates) that determines the + motion. For example, (0,0,1) is up-down, and means that up-down motion is what + determines how this joint moves. + + controllers: The various settings (e.g. spring force, mass) that determine how + the body part behaves. + */ + LLPhysicsMotion(const std::string ¶m_driver_name, + const std::string &joint_name, + LLCharacter *character, + const LLVector3 &motion_direction_vec, + const controller_map_t &controllers) : + mParamDriverName(param_driver_name), + mJointName(joint_name), + mMotionDirectionVec(motion_direction_vec), + mParamDriver(NULL), + mParamControllers(controllers), + mCharacter(character), + mLastTime(0), + mPosition_local(0), + mVelocityJoint_local(0), + mPositionLastUpdate_local(0) + { + mJointState = new LLJointState; + } + + BOOL initialize(); + + ~LLPhysicsMotion() {} + + BOOL onUpdate(F32 time, bool &bHandled); + + LLPointer getJointState() + { + return mJointState; + } +protected: + F32 getParamValue(const std::string& controller_key) + { + const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key); + if (entry == mParamControllers.end()) + { + return sDefaultController[controller_key]; + } + const std::string& param_name = (*entry).second.c_str(); + return mCharacter->getVisualParamWeight(param_name.c_str()); + } + void setParamValue(LLViewerVisualParam *param, + const F32 new_value_local, + F32 behavior_maxeffect); + + F32 toLocal(const LLVector3 &world); + F32 calculateVelocity_local(); + F32 calculateAcceleration_local(F32 velocity_local); +private: + const std::string mParamDriverName; + const std::string mParamControllerName; + const LLVector3 mMotionDirectionVec; + const std::string mJointName; + + F32 mPosition_local; + F32 mVelocityJoint_local; // How fast the joint is moving + F32 mAccelerationJoint_local; // Acceleration on the joint + + F32 mVelocity_local; // How fast the param is moving + F32 mPositionLastUpdate_local; + LLVector3 mPosition_world; + + LLViewerVisualParam *mParamDriver; + const controller_map_t mParamControllers; + + LLPointer mJointState; + LLCharacter *mCharacter; + + F32 mLastTime; + + static default_controller_map_t sDefaultController; +}; + +default_controller_map_t initDefaultController() +{ + default_controller_map_t controller; + controller["Mass"] = 0.2f; + controller["Gravity"] = 0.0f; + controller["Damping"] = .05f; + controller["Drag"] = 0.15f; + controller["MaxEffect"] = 0.1f; + controller["Spring"] = 0.1f; + controller["Gain"] = 10.0f; + return controller; +} + +default_controller_map_t LLPhysicsMotion::sDefaultController = initDefaultController(); + +BOOL LLPhysicsMotion::initialize() +{ + if (!mJointState->setJoint(mCharacter->getJoint(mJointName.c_str()))) + return FALSE; + mJointState->setUsage(LLJointState::ROT); + + mParamDriver = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamDriverName.c_str()); + if (mParamDriver == NULL) + { + llinfos << "Failure reading in [ " << mParamDriverName << " ]" << llendl; + return FALSE; + } + + return TRUE; +} + +LLPhysicsMotionController::LLPhysicsMotionController(const LLUUID &id) : + LLMotion(id), + mCharacter(NULL) +{ + mName = "breast_motion"; +} + +LLPhysicsMotionController::~LLPhysicsMotionController() +{ + for (motion_vec_t::iterator iter = mMotions.begin(); + iter != mMotions.end(); + ++iter) + { + delete (*iter); + } +} + +BOOL LLPhysicsMotionController::onActivate() +{ + return TRUE; +} + +void LLPhysicsMotionController::onDeactivate() +{ +} + +LLMotion::LLMotionInitStatus LLPhysicsMotionController::onInitialize(LLCharacter *character) +{ + mCharacter = character; + + mMotions.clear(); + + // Breast Cleavage + { + controller_map_t controller; + controller["Mass"] = "Breast_Physics_Mass"; + controller["Gravity"] = "Breast_Physics_Gravity"; + controller["Drag"] = "Breast_Physics_Drag"; + controller["Damping"] = "Breast_Physics_InOut_Damping"; + controller["MaxEffect"] = "Breast_Physics_InOut_Max_Effect"; + controller["Spring"] = "Breast_Physics_InOut_Spring"; + controller["Gain"] = "Breast_Physics_InOut_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_InOut_Controller", + "mChest", + character, + LLVector3(-1,0,0), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + + // Breast Bounce + { + controller_map_t controller; + controller["Mass"] = "Breast_Physics_Mass"; + controller["Gravity"] = "Breast_Physics_Gravity"; + controller["Drag"] = "Breast_Physics_Drag"; + controller["Damping"] = "Breast_Physics_UpDown_Damping"; + controller["MaxEffect"] = "Breast_Physics_UpDown_Max_Effect"; + controller["Spring"] = "Breast_Physics_UpDown_Spring"; + controller["Gain"] = "Breast_Physics_UpDown_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_UpDown_Controller", + "mChest", + character, + LLVector3(0,0,1), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + + // Breast Sway + { + controller_map_t controller; + controller["Mass"] = "Breast_Physics_Mass"; + controller["Gravity"] = "Breast_Physics_Gravity"; + controller["Drag"] = "Breast_Physics_Drag"; + controller["Damping"] = "Breast_Physics_LeftRight_Damping"; + controller["MaxEffect"] = "Breast_Physics_LeftRight_Max_Effect"; + controller["Spring"] = "Breast_Physics_LeftRight_Spring"; + controller["Gain"] = "Breast_Physics_LeftRight_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_LeftRight_Controller", + "mChest", + character, + LLVector3(0,-1,0), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + // Butt Bounce + { + controller_map_t controller; + controller["Mass"] = "Butt_Physics_Mass"; + controller["Gravity"] = "Butt_Physics_Gravity"; + controller["Drag"] = "Butt_Physics_Drag"; + controller["Damping"] = "Butt_Physics_UpDown_Damping"; + controller["MaxEffect"] = "Butt_Physics_UpDown_Max_Effect"; + controller["Spring"] = "Butt_Physics_UpDown_Spring"; + controller["Gain"] = "Butt_Physics_UpDown_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_UpDown_Controller", + "mPelvis", + character, + LLVector3(0,0,-1), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + + // Butt LeftRight + { + controller_map_t controller; + controller["Mass"] = "Butt_Physics_Mass"; + controller["Gravity"] = "Butt_Physics_Gravity"; + controller["Drag"] = "Butt_Physics_Drag"; + controller["Damping"] = "Butt_Physics_LeftRight_Damping"; + controller["MaxEffect"] = "Butt_Physics_LeftRight_Max_Effect"; + controller["Spring"] = "Butt_Physics_LeftRight_Spring"; + controller["Gain"] = "Butt_Physics_LeftRight_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_LeftRight_Controller", + "mPelvis", + character, + LLVector3(0,-1,0), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + + // Belly Bounce + { + controller_map_t controller; + controller["Mass"] = "Belly_Physics_Mass"; + controller["Gravity"] = "Belly_Physics_Gravity"; + controller["Drag"] = "Belly_Physics_Drag"; + controller["Damping"] = "Belly_Physics_UpDown_Damping"; + controller["MaxEffect"] = "Belly_Physics_UpDown_Max_Effect"; + controller["Spring"] = "Belly_Physics_UpDown_Spring"; + controller["Gain"] = "Belly_Physics_UpDown_Gain"; + LLPhysicsMotion *motion = new LLPhysicsMotion("Belly_Physics_UpDown_Controller", + "mPelvis", + character, + LLVector3(0,0,-1), + controller); + if (!motion->initialize()) + { + llassert_always(FALSE); + return STATUS_FAILURE; + } + addMotion(motion); + } + + return STATUS_SUCCESS; +} + +void LLPhysicsMotionController::addMotion(LLPhysicsMotion *motion) +{ + addJointState(motion->getJointState()); + mMotions.push_back(motion); +} + +F32 LLPhysicsMotionController::getMinPixelArea() +{ + return MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION; +} + +// Local space means "parameter space". +F32 LLPhysicsMotion::toLocal(const LLVector3 &world) +{ + LLJoint *joint = mJointState->getJoint(); + const LLQuaternion rotation_world = joint->getWorldRotation(); + + LLVector3 dir_world = mMotionDirectionVec * rotation_world; + dir_world.normalize(); + return world * dir_world; +} + +F32 LLPhysicsMotion::calculateVelocity_local() +{ + const F32 world_to_model_scale = 100.0f; + LLJoint *joint = mJointState->getJoint(); + const LLVector3 position_world = joint->getWorldPosition(); + const LLQuaternion rotation_world = joint->getWorldRotation(); + const LLVector3 last_position_world = mPosition_world; + const LLVector3 positionchange_world = (position_world-last_position_world) * world_to_model_scale; + const LLVector3 velocity_world = positionchange_world; + const F32 velocity_local = toLocal(velocity_world); + return velocity_local; +} + +F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local) +{ +// const F32 smoothing = getParamValue("Smoothing"); + static const F32 smoothing = 3.0f; // Removed smoothing param since it's probably not necessary + const F32 acceleration_local = velocity_local - mVelocityJoint_local; + + const F32 smoothed_acceleration_local = + acceleration_local * 1.0/smoothing + + mAccelerationJoint_local * (smoothing-1.0)/smoothing; + + return smoothed_acceleration_local; +} + +BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) +{ + // Skip if disabled globally. + /*if (!gSavedSettings.getBOOL("AvatarPhysics")) + { + return TRUE; + }*/ + + BOOL update_visuals = FALSE; + bool physics_handled = false; + for (motion_vec_t::iterator iter = mMotions.begin(); + iter != mMotions.end(); + ++iter) + { + LLPhysicsMotion *motion = (*iter); + bool bHandled; + update_visuals |= motion->onUpdate(time,bHandled); + physics_handled |= bHandled; + } + + if (update_visuals) + mCharacter->updateVisualParams(); + + if(!physics_handled && mCharacter) //If absolutely nothing was done, and it wasn't due to timers/lod + ((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); + return TRUE; +} + + +// Return TRUE if character has to update visual params. +BOOL LLPhysicsMotion::onUpdate(F32 time, bool &bHandled) +{ + bHandled = false; + // static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w"); + + if (!mParamDriver) + return FALSE; + + if (!mLastTime) + { + mLastTime = time; + return FALSE; + } + + //////////////////////////////////////////////////////////////////////////////// + // Get all parameters and settings + // + + const F32 time_delta = time - mLastTime; + + bHandled = true; + // Don't update too frequently, to avoid precision errors from small time slices. + if (time_delta <= .01) + { + return FALSE; + } + + // If less than 1FPS, we don't want to be spending time updating physics at all. + if (time_delta > 1.0) + { + mLastTime = time; + return FALSE; + } + + // Higher LOD is better. This controls the granularity + // and frequency of updates for the motions. + const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor; + if (lod_factor == 0) + { + return TRUE; + } + + LLJoint *joint = mJointState->getJoint(); + + const F32 behavior_mass = getParamValue("Mass"); + const F32 behavior_gravity = getParamValue("Gravity"); + const F32 behavior_spring = getParamValue("Spring"); + const F32 behavior_gain = getParamValue("Gain"); + const F32 behavior_damping = getParamValue("Damping"); + const F32 behavior_drag = getParamValue("Drag"); + const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. + + F32 behavior_maxeffect = getParamValue("MaxEffect"); + if (physics_test) + behavior_maxeffect = 1.0f; + + // Normalize the param position to be from [0,1]. + // We have to use normalized values because there may be more than one driven param, + // and each of these driven params may have its own range. + // This means we'll do all our calculations in normalized [0,1] local coordinates. + const F32 position_user_local = (mParamDriver->getWeight() - mParamDriver->getMinWeight()) / (mParamDriver->getMaxWeight() - mParamDriver->getMinWeight()); + + // + // End parameters and settings + //////////////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////////////////// + // Calculate velocity and acceleration in parameter space. + // + + //const F32 velocity_joint_local = calculateVelocity_local(time_iteration_step); + const F32 velocity_joint_local = calculateVelocity_local(); + const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local); + + // + // End velocity and acceleration + //////////////////////////////////////////////////////////////////////////////// + + BOOL update_visuals = FALSE; + + // Break up the physics into a bunch of iterations so that differing framerates will show + // roughly the same behavior. + for (F32 time_iteration = 0; time_iteration <= time_delta; time_iteration += TIME_ITERATION_STEP) + { + F32 time_iteration_step = TIME_ITERATION_STEP; + if (time_iteration + TIME_ITERATION_STEP > time_delta) + { + time_iteration_step = time_delta-time_iteration; + } + + // mPositon_local should be in normalized 0,1 range already. Just making sure... + const F32 position_current_local = llclamp(mPosition_local, + 0.0f, + 1.0f); + // If the effect is turned off then don't process unless we need one more update + // to set the position to the default (i.e. user) position. + if ((behavior_maxeffect == 0) && (position_current_local == position_user_local)) + { + bHandled = false; //Let emerald boob stuff do its thing, possibly. + return update_visuals; + } + + //////////////////////////////////////////////////////////////////////////////// + // Calculate the total force + // + + // Spring force is a restoring force towards the original user-set breast position. + // F = kx + const F32 spring_length = position_current_local - position_user_local; + const F32 force_spring = -spring_length * behavior_spring; + + // Acceleration is the force that comes from the change in velocity of the torso. + // F = ma + const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass); + + // Gravity always points downward in world space. + // F = mg + const LLVector3 gravity_world(0,0,1); + const F32 force_gravity = (toLocal(gravity_world) * behavior_gravity * behavior_mass); + + // Damping is a restoring force that opposes the current velocity. + // F = -kv + const F32 force_damping = -behavior_damping * mVelocity_local; + + // Drag is a force imparted by velocity (intuitively it is similar to wind resistance) + // F = .5kv^2 + const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local); + + const F32 force_net = (force_accel + + force_gravity + + force_spring + + force_damping + + force_drag); + + // + // End total force + //////////////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////////////////// + // Calculate new params + // + + // Calculate the new acceleration based on the net force. + // a = F/m + const F32 acceleration_new_local = force_net / behavior_mass; + static const F32 max_velocity = 100.0f; // magic number, used to be customizable. + F32 velocity_new_local = mVelocity_local + acceleration_new_local*time_iteration_step; + velocity_new_local = llclamp(velocity_new_local, + -max_velocity, max_velocity); + + // Temporary debugging setting to cause all avatars to move, for profiling purposes. + if (physics_test) + { + velocity_new_local = sin(time*4.0); + } + // Calculate the new parameters, or remain unchanged if max speed is 0. + F32 position_new_local = position_current_local + velocity_new_local*time_iteration_step; + if (behavior_maxeffect == 0) + position_new_local = position_user_local; + + // Zero out the velocity if the param is being pushed beyond its limits. + if ((position_new_local < 0 && velocity_new_local < 0) || + (position_new_local > 1 && velocity_new_local > 0)) + { + velocity_new_local = 0; + } + + // Check for NaN values. A NaN value is detected if the variables doesn't equal itself. + // If NaN, then reset everything. + if ((mPosition_local != mPosition_local) || + (mVelocity_local != mVelocity_local) || + (position_new_local != position_new_local)) + { + position_new_local = 0; + mVelocity_local = 0; + mVelocityJoint_local = 0; + mAccelerationJoint_local = 0; + mPosition_local = 0; + mPosition_world = LLVector3(0,0,0); + } + + const F32 position_new_local_clamped = llclamp(position_new_local, + 0.0f, + 1.0f); + + LLDriverParam *driver_param = dynamic_cast(mParamDriver); + llassert_always(driver_param); + if (driver_param) + { + // If this is one of our "hidden" driver params, then make sure it's + // the default value. + if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && + (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT)) + { + mCharacter->setVisualParamWeight(driver_param, + 0, + FALSE); + } + for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); + iter != driver_param->mDriven.end(); + ++iter) + { + LLDrivenEntry &entry = (*iter); + LLViewerVisualParam *driven_param = entry.mParam; + setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); + } + } + + // + // End calculate new params + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + // Conditionally update the visual params + // + + // Updating the visual params (i.e. what the user sees) is fairly expensive. + // So only update if the params have changed enough, and also take into account + // the graphics LOD settings. + + // For non-self, if the avatar is small enough visually, then don't update. + const F32 area_for_max_settings = 0.0; + const F32 area_for_min_settings = 1400.0; + const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); + const F32 pixel_area = fsqrtf(mCharacter->getPixelArea()); + + const BOOL is_self = (dynamic_cast(mCharacter) != NULL && ((LLVOAvatar*)mCharacter)->isSelf()); + if ((pixel_area > area_for_this_setting) || is_self) + { + const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped); + const F32 min_delta = (1.0001f-lod_factor)*0.4f; + if (llabs(position_diff_local) > min_delta) + { + update_visuals = TRUE; + mPositionLastUpdate_local = position_new_local; + } + } + + // + // End update visual params + //////////////////////////////////////////////////////////////////////////////// + + mVelocity_local = velocity_new_local; + mAccelerationJoint_local = acceleration_joint_local; + mPosition_local = position_new_local; + } + mLastTime = time; + mPosition_world = joint->getWorldPosition(); + mVelocityJoint_local = velocity_joint_local; + + + /* + // Write out debugging info into a spreadsheet. + if (mFileWrite != NULL && is_self) + { + fprintf(mFileWrite,"%f\t%f\t%f \t\t%f \t\t%f\t%f\t%f\t \t\t%f\t%f\t%f\t%f\t%f \t\t%f\t%f\t%f\n", + position_new_local, + velocity_new_local, + acceleration_new_local, + + time_delta, + + mPosition_world[0], + mPosition_world[1], + mPosition_world[2], + + force_net, + force_spring, + force_accel, + force_damping, + force_drag, + + spring_length, + velocity_joint_local, + acceleration_joint_local + ); + } + */ + + return update_visuals; +} + +// Range of new_value_local is assumed to be [0 , 1] normalized. +void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param, + F32 new_value_normalized, + F32 behavior_maxeffect) +{ + const F32 value_min_local = param->getMinWeight(); + const F32 value_max_local = param->getMaxWeight(); + const F32 min_val = 0.5f-behavior_maxeffect/2.0; + const F32 max_val = 0.5f+behavior_maxeffect/2.0; + + // Scale from [0,1] to [min_val,max_val] + const F32 new_value_rescaled = min_val + (max_val-min_val) * new_value_normalized; + + // Scale from [0,1] to [value_min_local,value_max_local] + const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_rescaled; + + mCharacter->setVisualParamWeight(param, + new_value_local, + FALSE); +} diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h new file mode 100644 index 000000000..657698e4f --- /dev/null +++ b/indra/newview/llphysicsmotion.h @@ -0,0 +1,124 @@ +/** + * @file llphysicsmotion.h + * @brief Implementation of LLPhysicsMotion class. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPHYSICSMOTIONCONTROLLER_H +#define LL_LLPHYSICSMOTIONCONTROLLER_H + +//----------------------------------------------------------------------------- +// Header files +//----------------------------------------------------------------------------- +#include "llmotion.h" +#include "llframetimer.h" + +#define PHYSICS_MOTION_FADEIN_TIME 1.0f +#define PHYSICS_MOTION_FADEOUT_TIME 1.0f + +class LLPhysicsMotion; + +//----------------------------------------------------------------------------- +// class LLPhysicsMotion +//----------------------------------------------------------------------------- +class LLPhysicsMotionController : + public LLMotion +{ +public: + // Constructor + LLPhysicsMotionController(const LLUUID &id); + + // Destructor + virtual ~LLPhysicsMotionController(); + +public: + //------------------------------------------------------------------------- + // functions to support MotionController and MotionRegistry + //------------------------------------------------------------------------- + + // static constructor + // all subclasses must implement such a function and register it + static LLMotion *create(const LLUUID &id) { return new LLPhysicsMotionController(id); } + +public: + //------------------------------------------------------------------------- + // animation callbacks to be implemented by subclasses + //------------------------------------------------------------------------- + + // motions must specify whether or not they loop + virtual BOOL getLoop() { return TRUE; } + + // motions must report their total duration + virtual F32 getDuration() { return 0.0; } + + // motions must report their "ease in" duration + virtual F32 getEaseInDuration() { return PHYSICS_MOTION_FADEIN_TIME; } + + // motions must report their "ease out" duration. + virtual F32 getEaseOutDuration() { return PHYSICS_MOTION_FADEOUT_TIME; } + + // called to determine when a motion should be activated/deactivated based on avatar pixel coverage + virtual F32 getMinPixelArea(); + + // motions must report their priority + virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; } + + virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; } + + // run-time (post constructor) initialization, + // called after parameters have been set + // must return true to indicate success and be available for activation + virtual LLMotionInitStatus onInitialize(LLCharacter *character); + + // called when a motion is activated + // must return TRUE to indicate success, or else + // it will be deactivated + virtual BOOL onActivate(); + + // called per time step + // must return TRUE while it is active, and + // must return FALSE when the motion is completed. + virtual BOOL onUpdate(F32 time, U8* joint_mask); + + // called when a motion is deactivated + virtual void onDeactivate(); + + LLCharacter* getCharacter() { return mCharacter; } + +protected: + void addMotion(LLPhysicsMotion *motion); +private: + LLCharacter* mCharacter; + + typedef std::vector motion_vec_t; + motion_vec_t mMotions; +}; + +#endif // LL_LLPHYSICSMOTION_H + diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index dbe6079ed..a23c199c9 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -49,7 +49,16 @@ #define HEADER_ASCII "Linden Mesh 1.0" #define HEADER_BINARY "Linden Binary Mesh 1.0" -extern LLControlGroup gSavedSettings; // read only +extern LLControlGroup gSavedSettings; // read only + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name); +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name); +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name); //----------------------------------------------------------------------------- // Global table of loaded LLPolyMeshes @@ -606,8 +615,60 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) continue; } - mMorphData.insert(morph_data); - } + mMorphData.insert(morph_data); + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_cleavage(morph_data, + .75f, + "Breast_Physics_LeftRight_Driven")); + } + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_InOut_Driven")); + } + if (!strcmp(morphName, "Breast_Gravity")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Torso")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Torso_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Legs")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Legs_UpDown_Driven")); + } + + if (!strcmp(morphName, "skirt_belly")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Skirt_UpDown_Driven")); + } + + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Butt_Physics_UpDown_Driven")); + } + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0.03f,0), + "Butt_Physics_LeftRight_Driven")); + } + } S32 numRemaps; if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) @@ -1156,4 +1217,55 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex ) mLastWeight = mCurWeight; } + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = src_data->mCoords[v]; + cloned_morph_data->mNormals[v] = src_data->mNormals[v]; + cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = direction; + cloned_morph_data->mNormals[v] = LLVector3(0,0,0); + cloned_morph_data->mBinormals[v] = LLVector3(0,0,0); + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = src_data->mCoords[v]*scale; + cloned_morph_data->mNormals[v] = src_data->mNormals[v]*scale; + cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]*scale; + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v][1] *= -1; + cloned_morph_data->mNormals[v][1] *= -1; + cloned_morph_data->mBinormals[v][1] *= -1; + } + } + return cloned_morph_data; +} + // End diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 3a57b6f9f..72a332440 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -64,6 +64,36 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) mMesh = NULL; } +LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : + mName(rhs.mName), + mNumIndices(rhs.mNumIndices), + mTotalDistortion(rhs.mTotalDistortion), + mAvgDistortion(rhs.mAvgDistortion), + mMaxDistortion(rhs.mMaxDistortion), + mVertexIndices(NULL), + mCoords(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL) +{ + const S32 numVertices = mNumIndices; + + mCoords = new LLVector3[numVertices]; + mNormals = new LLVector3[numVertices]; + mBinormals = new LLVector3[numVertices]; + mTexCoords = new LLVector2[numVertices]; + mVertexIndices = new U32[numVertices]; + + for (S32 v=0; v < numVertices; v++) + { + mCoords[v] = rhs.mCoords[v]; + mNormals[v] = rhs.mNormals[v]; + mBinormals[v] = rhs.mBinormals[v]; + mTexCoords[v] = rhs.mTexCoords[v]; + mVertexIndices[v] = rhs.mVertexIndices[v]; + } +} + //----------------------------------------------------------------------------- // ~LLPolyMorphData() //----------------------------------------------------------------------------- @@ -292,10 +322,22 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) } } - mMorphData = mMesh->getMorphData(getInfo()->mMorphName); + std::string morph_param_name = getInfo()->mMorphName; + + mMorphData = mMesh->getMorphData(morph_param_name); if (!mMorphData) { - llwarns << "No morph target named " << getInfo()->mMorphName << " found in mesh." << llendl; + const std::string driven_tag = "_Driven"; + U32 pos = morph_param_name.find(driven_tag); + if (pos > 0) + { + morph_param_name = morph_param_name.substr(0,pos); + mMorphData = mMesh->getMorphData(morph_param_name); + } + } + if (!mMorphData) + { + llwarns << "No morph target named " << morph_param_name << " found in mesh." << llendl; return FALSE; // Continue, ignoring this tag } return TRUE; @@ -445,6 +487,16 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) mLastSex = avatar_sex; + // Check for NaN condition (NaN is detected if a variable doesn't equal itself. + if (mCurWeight != mCurWeight) + { + mCurWeight = 0.0; + } + if (mLastWeight != mLastWeight) + { + mLastWeight = mCurWeight+.001; + } + // perform differential update of morph F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); // store last weight diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index f8dd52ca3..3fdaf3785 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -51,6 +51,7 @@ class LLPolyMorphData public: LLPolyMorphData(const std::string& morph_name); ~LLPolyMorphData(); + LLPolyMorphData(const LLPolyMorphData &rhs); BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); const std::string& getName() { return mName; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 956e31502..b75c3345e 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3913,6 +3913,7 @@ class LLEditEnableCustomizeAvatar : public view_listener_t } }; + class LLEditEnableChangeDisplayname : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -8894,6 +8895,10 @@ class LLEditEnableTakeOff : public view_listener_t { new_value = LLAgent::selfHasWearable((void *)WT_TATTOO); } + if (clothing == "physics") + { + new_value = LLAgent::selfHasWearable((void *)WT_PHYSICS); + } // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b | OK // Why aren't they using LLWearable::typeNameToType()? *confuzzled* @@ -8957,6 +8962,10 @@ class LLEditTakeOff : public view_listener_t { LLAgent::userRemoveWearable((void*)WT_TATTOO); } + else if (clothing == "physics") + { + LLAgent::userRemoveWearable((void*)WT_PHYSICS); + } else if (clothing == "all") { LLAgent::userRemoveAllClothes(NULL); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5f1749ddd..c1d9f11a9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -103,6 +103,8 @@ #include "llavatarname.h" #include "llavatarnamecache.h" +#include "llphysicsmotion.h" + // [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) #include "rlvhandler.h" // [/RLVa:KB] @@ -128,6 +130,7 @@ const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d" const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix" const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target" const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" +const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion" //----------------------------------------------------------------------------- @@ -720,6 +723,7 @@ BOOL LLVOAvatar::sShowAnimationDebug = FALSE; BOOL LLVOAvatar::sShowFootPlane = FALSE; BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; F32 LLVOAvatar::sLODFactor = 1.f; +F32 LLVOAvatar::sPhysicsLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; @@ -1016,6 +1020,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, // motions without a start/stop bit registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create ); registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create ); + registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create ); registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create ); registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create ); registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create ); @@ -1970,6 +1975,7 @@ void LLVOAvatar::startDefaultMotions() startMotion( ANIM_AGENT_EYE ); startMotion( ANIM_AGENT_BODY_NOISE ); startMotion( ANIM_AGENT_BREATHE_ROT ); + startMotion( ANIM_AGENT_PHYSICS_MOTION ); startMotion( ANIM_AGENT_HAND_MOTION ); startMotion( ANIM_AGENT_PELVIS_FIX ); @@ -2791,7 +2797,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) idleUpdateAppearanceAnimation(); if (detailed_update) { - idleUpdateBoobEffect(); + //idleUpdateBoobEffect(); idleUpdateLipSync( voice_enabled ); idleUpdateLoadingEffect(); idleUpdateBelowWater(); // wind effect uses this @@ -9151,6 +9157,13 @@ void LLVOAvatar::wearableUpdated(EWearableType type, BOOL upload_result) } } } + + // Physics type has no associated baked textures, but change of params needs to be sent to + // other avatars. + if (isSelf() && type == WT_PHYSICS) + { + gAgent.sendAgentSetAppearance(); + } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 4bedcbb10..0ea151b12 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -55,6 +55,7 @@ extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; +extern const LLUUID ANIM_AGENT_PHYSICS_MOTION; extern const LLUUID ANIM_AGENT_EDITING; extern const LLUUID ANIM_AGENT_EYE; extern const LLUUID ANIM_AGENT_FLY_ADJUST; @@ -629,6 +630,7 @@ public: static BOOL sDebugInvisible; static BOOL sShowAttachmentPoints; static F32 sLODFactor; // user-settable LOD factor + static F32 sPhysicsLODFactor; // user-settable physics LOD factor static BOOL sJointDebug; // output total number of joints being touched for each avatar static BOOL sDebugAvatarRotation; static F32 sAvMorphTime; diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 14c6220c5..e85726166 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -72,6 +72,7 @@ const std::string LLWearable::sTypeName[ WT_COUNT+1 ] = "skirt", "alpha", "tattoo", + "physics", "invalid" }; @@ -93,6 +94,7 @@ const std::string LLWearable::sTypeLabel[ WT_COUNT+1 ] = "Skirt", "Alpha", "Tattoo", + "Physics", "invalid" }; @@ -118,6 +120,7 @@ LLAssetType::EType LLWearable::typeToAssetType(EWearableType wearable_type) case WT_SKIRT: case WT_ALPHA: case WT_TATTOO: + case WT_PHYSICS: return LLAssetType::AT_CLOTHING; default: return LLAssetType::AT_NONE; diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 253ae97b0..72d876359 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -58,7 +58,8 @@ enum EWearableType // If you change this, update LLWearable::getTypeName(), get WT_SKIRT = 12, WT_ALPHA = 13, WT_TATTOO = 14, - WT_COUNT = 15, + WT_PHYSICS = 15, + WT_COUNT = 16, WT_INVALID = 255 }; diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 8fb992e0c..94b88fb0c 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1993,7 +1993,7 @@ ERlvCmdRet RlvHandler::onGetOutfit(const RlvCommand& rlvCmd, std::string& strRep const EWearableType wtRlvTypes[] = { WT_GLOVES, WT_JACKET, WT_PANTS, WT_SHIRT, WT_SHOES, WT_SKIRT, WT_SOCKS, - WT_UNDERPANTS, WT_UNDERSHIRT, WT_SKIN, WT_EYES, WT_HAIR, WT_SHAPE, WT_ALPHA, WT_TATTOO + WT_UNDERPANTS, WT_UNDERSHIRT, WT_SKIN, WT_EYES, WT_HAIR, WT_SHAPE, WT_ALPHA, WT_TATTOO, WT_PHYSICS }; for (int idxType = 0, cntType = sizeof(wtRlvTypes) / sizeof(EWearableType); idxType < cntType; idxType++) diff --git a/indra/newview/skins/default/textures/inv_item_physics.png b/indra/newview/skins/default/textures/inv_item_physics.png new file mode 100644 index 0000000000000000000000000000000000000000..360baec46d291923ec07f574df9022178f7c640a GIT binary patch literal 539 zcmV+$0_6RPP)tQ^=kX}?XQ5E zUwyfAyd5kj$?~5V7kKgfc=nx#hlfF5Umq;M_4B10&|vNV;<}A6L+}NnHBiG$#&^-8 zOwa!?Faq)KXTL>(^c6vNyn*%ih=BN46fS@fFArphg*xq2F#D*oPhlj3CXT48Ise7=AOr>Hoih z^e-U)H-pT}4f~~}q?~{TtoqBu=D@1yC5GWykRfXS5_^zr_kg(oiur&BgyT#H$C#Ed z0&Oma2|oGwJM!zVf4Beq`+xT1kH3$fe*EnS6n>1&0C+5b41uw?U;hZAUIB485N`nD z*QP-M$8fp;3%G(t;{+H6G_Jb@O0J$Dc72fEC#Y~bP+SIx`G|1=DAR!aupP=j3dA6d d{7^X*008*3-Imx&5t;x1002ovPDHLkV1h7h@8tjh literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/xui/en-us/floater_inventory.xml b/indra/newview/skins/default/xui/en-us/floater_inventory.xml index 4832c5132..d42d855d6 100644 --- a/indra/newview/skins/default/xui/en-us/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en-us/floater_inventory.xml @@ -160,6 +160,10 @@ mouse_opaque="true" name="New Alpha" width="125"> + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_inventory.xml b/indra/newview/skins/default/xui/en-us/menu_inventory.xml index 64f294599..9265e688a 100644 --- a/indra/newview/skins/default/xui/en-us/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en-us/menu_inventory.xml @@ -96,6 +96,10 @@ mouse_opaque="true" name="New Alpha" width="128"> + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml index a73400803..aa3f5b756 100644 --- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml @@ -196,7 +196,12 @@ - + + + + From 8b12d794c5b2b87dafd03b4fa3011d6fcc8782f8 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 28 Apr 2011 22:47:48 -0500 Subject: [PATCH 2/9] Added physics saved settings. Emerald physics demoted to legacy. Only enabled on av's that fail to send physics paramaters, or AvatarPhysics is completely disabled. Params reset when AvatarPhysics is toggled off. (Bugfix for LL's code) --- indra/newview/app_settings/settings.xml | 22 +++++++++ indra/newview/llappviewer.cpp | 1 + indra/newview/llphysicsmotion.cpp | 60 ++++++++++++++++++------- indra/newview/llphysicsmotion.h | 3 +- indra/newview/llviewercontrol.cpp | 7 +++ indra/newview/llvoavatar.cpp | 11 ++++- indra/newview/llvoavatar.h | 3 ++ 7 files changed, 89 insertions(+), 18 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 537a22a41..62c638440 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1739,6 +1739,17 @@ Value 2 + AvatarPhysics + + Comment + Enable avatar wearable physics. + Persist + 1 + Type + Boolean + Value + 1 + AvatarSex Comment @@ -8842,6 +8853,17 @@ Value 35 + RenderAvatarPhysicsLODFactor + + Comment + Controls level of detail of avatar physics (such as breast physics). + Persist + 1 + Type + F32 + Value + 1.0 + RenderAvatarInvisible Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 39eba7877..38ae9202e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -429,6 +429,7 @@ static void settings_to_globals() LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor"); + LLVOAvatar::sPhysicsLODFactor = gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible"); // clamp auto-open time to some minimum usable value diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index 59434a1f1..475e153c5 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -111,12 +111,14 @@ public: ~LLPhysicsMotion() {} - BOOL onUpdate(F32 time, bool &bHandled); + BOOL onUpdate(F32 time); LLPointer getJointState() { return mJointState; } + + void reset(); protected: F32 getParamValue(const std::string& controller_key) { @@ -135,6 +137,7 @@ protected: F32 toLocal(const LLVector3 &world); F32 calculateVelocity_local(); F32 calculateAcceleration_local(F32 velocity_local); + private: const std::string mParamDriverName; const std::string mParamControllerName; @@ -193,7 +196,8 @@ BOOL LLPhysicsMotion::initialize() LLPhysicsMotionController::LLPhysicsMotionController(const LLUUID &id) : LLMotion(id), - mCharacter(NULL) + mCharacter(NULL), + mIsDefault(true) { mName = "breast_motion"; } @@ -210,11 +214,13 @@ LLPhysicsMotionController::~LLPhysicsMotionController() BOOL LLPhysicsMotionController::onActivate() { + llinfos << "LLPhysicsMotionController activate" << llendl; return TRUE; } void LLPhysicsMotionController::onDeactivate() { + llinfos << "LLPhysicsMotionController deactivate" << llendl; } LLMotion::LLMotionInitStatus LLPhysicsMotionController::onInitialize(LLCharacter *character) @@ -414,36 +420,42 @@ F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local) BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) { // Skip if disabled globally. - /*if (!gSavedSettings.getBOOL("AvatarPhysics")) + static const LLCachedControl avatar_physics("AvatarPhysics",false); + if (!avatar_physics || (!((LLVOAvatar*)mCharacter)->isSelf() && !((LLVOAvatar*)mCharacter)->mSupportsPhysics)) { - return TRUE; - }*/ + if(!mIsDefault) + { + mIsDefault = true; + for (motion_vec_t::iterator iter = mMotions.begin();iter != mMotions.end();++iter) + { + (*iter)->reset(); + } + mCharacter->updateVisualParams(); + } + ((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); //Fall back to emerald physics + return TRUE; + } + mIsDefault = false; + BOOL update_visuals = FALSE; - bool physics_handled = false; for (motion_vec_t::iterator iter = mMotions.begin(); iter != mMotions.end(); ++iter) { LLPhysicsMotion *motion = (*iter); - bool bHandled; - update_visuals |= motion->onUpdate(time,bHandled); - physics_handled |= bHandled; + update_visuals |= motion->onUpdate(time); } if (update_visuals) mCharacter->updateVisualParams(); - if(!physics_handled && mCharacter) //If absolutely nothing was done, and it wasn't due to timers/lod - ((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); return TRUE; } - // Return TRUE if character has to update visual params. -BOOL LLPhysicsMotion::onUpdate(F32 time, bool &bHandled) +BOOL LLPhysicsMotion::onUpdate(F32 time) { - bHandled = false; // static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w"); if (!mParamDriver) @@ -461,7 +473,6 @@ BOOL LLPhysicsMotion::onUpdate(F32 time, bool &bHandled) const F32 time_delta = time - mLastTime; - bHandled = true; // Don't update too frequently, to avoid precision errors from small time slices. if (time_delta <= .01) { @@ -540,7 +551,6 @@ BOOL LLPhysicsMotion::onUpdate(F32 time, bool &bHandled) // to set the position to the default (i.e. user) position. if ((behavior_maxeffect == 0) && (position_current_local == position_user_local)) { - bHandled = false; //Let emerald boob stuff do its thing, possibly. return update_visuals; } @@ -745,3 +755,21 @@ void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param, new_value_local, FALSE); } + +void LLPhysicsMotion::reset() +{ + LLDriverParam *driver_param = dynamic_cast(mParamDriver); + if (driver_param) + { + if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && + (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT)) + { + mCharacter->setVisualParamWeight(driver_param,driver_param->getDefaultWeight()); + } + for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); + iter != driver_param->mDriven.end();++iter) + { + mCharacter->setVisualParamWeight((*iter).mParam,(*iter).mParam->getDefaultWeight()); + } + } +} \ No newline at end of file diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h index 657698e4f..3ee44f8d5 100644 --- a/indra/newview/llphysicsmotion.h +++ b/indra/newview/llphysicsmotion.h @@ -110,7 +110,6 @@ public: virtual void onDeactivate(); LLCharacter* getCharacter() { return mCharacter; } - protected: void addMotion(LLPhysicsMotion *motion); private: @@ -118,6 +117,8 @@ private: typedef std::vector motion_vec_t; motion_vec_t mMotions; + + bool mIsDefault; }; #endif // LL_LLPHYSICSMOTION_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8af25724f..22609c938 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -216,6 +216,12 @@ static bool handleAvatarLODChanged(const LLSD& newvalue) return true; } +static bool handleAvatarPhysicsLODChanged(const LLSD& newvalue) +{ + LLVOAvatar::sLODFactor = (F32) newvalue.asReal(); + return true; +} + static bool handleAvatarMaxVisibleChanged(const LLSD& newvalue) { LLVOAvatar::sMaxVisible = (U32) newvalue.asInteger(); @@ -583,6 +589,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1)); gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _1)); + gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _1)); gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _1)); gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&handleBandwidthChanged, _1)); gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _1)); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c1d9f11a9..9624a2151 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -795,7 +795,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFullyLoadedInitialized(FALSE), mHasBakedHair( FALSE ), mSupportsAlphaLayers(FALSE), - mFirstSetActualBoobGravRan( false ) + mFirstSetActualBoobGravRan( false ), + mSupportsPhysics( false ) //mFirstSetActualButtGravRan( false ), //mFirstSetActualFatGravRan( false ) // @@ -9368,6 +9369,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) updateMeshTextures(); // enables updates for laysets without baked textures. + mSupportsPhysics = false; + // parse visual params S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); if( num_blocks > 1 ) @@ -9400,6 +9403,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + if(param->getID() == 10000) + { + mSupportsPhysics = true; + } if(param->getID() == 507 && newWeight != getActualBoobGrav()) { llwarns << "Boob Grav SET to " << newWeight << " for " << getFullname() << llendl; @@ -9444,6 +9451,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { if (param->getName() == "tattoo_red") llinfos << getFullname() << " does not have tattoo tinting." << llendl; + else if(param->getName() == "breast_physics_leftright_spring") + llinfos << getFullname() << " does not have avatar physics." << llendl; else llwarns << "Number of params in AvatarAppearance msg does not match number of params in avatar xml file for " << getFullname() << " (Prematurely reached end of list at " << param->getName() << ")." << llendl; //return; //ASC-TTRFE diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 0ea151b12..e21337c90 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -99,6 +99,9 @@ public: void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); std::string extraMetadata; // + + // EmeraldBoobUtils + bool mSupportsPhysics; //Client supports v2 wearable physics. Disable emerald physics. //-------------------------------------------------------------------- // LLViewerObject interface From d2f66f9bd0a1c815160730330474a94191b7a2a2 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Fri, 29 Apr 2011 00:24:07 -0500 Subject: [PATCH 3/9] LLTextureCache is spamming warnings as it attempts to remove non-existant files. Not sure if this is a bug or not, but it's been this way for a while now, so I'm squelching it. --- indra/newview/lltexturecache.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 1716b5c5d..5c27e365a 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -915,10 +915,12 @@ void LLTextureCache::purgeCache(ELLPath location) if(LLFile::isdir(mTexturesDirName)) { std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename); - LLAPRFile::remove(file_name); + if(LLAPRFile::isExist(file_name)) + LLAPRFile::remove(file_name); file_name = gDirUtilp->getExpandedFilename(location, cache_filename); - LLAPRFile::remove(file_name); + if(LLAPRFile::isExist(file_name)) + LLAPRFile::remove(file_name); purgeAllTextures(true); } @@ -1711,7 +1713,8 @@ void LLTextureCache::purgeTextureFilesTimeSliced(bool force) if (mHeaderIDMap.find(curiter->first) == mHeaderIDMap.end()) { filename = curiter->second; - LLAPRFile::remove(filename); + if(LLAPRFile::isExist(filename)) + LLAPRFile::remove(filename); } else { @@ -1963,7 +1966,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename, b mFreeList.insert(idx); } - if (remove_file) + if (remove_file && LLAPRFile::isExist(filename)) { LLAPRFile::remove(filename); } From a6947425220a07fe907b87d68ce0f2d4599ae092 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Fri, 29 Apr 2011 03:39:05 -0500 Subject: [PATCH 4/9] Added physics subpanel to avatar customize floater. Also, removed redundant tattoo and alpha entries. Modified LLScrollingPanelParam to work without needing 'hints'. A bit hacky since I didn't want to dive into making yet another xml, but works well enough. Avatar_lad entries names changed to more readable forms since LLTrans isn't where it needs to be yet. Camera doesn't move to great positions when editing phys parts, but that's for another day. --- indra/newview/character/avatar_lad.xml | 66 ++--- indra/newview/llfloatercustomize.cpp | 276 +++++++++++------- indra/newview/llfloatercustomize.h | 2 +- .../default/xui/en-us/floater_customize.xml | 94 +++++- 4 files changed, 291 insertions(+), 147 deletions(-) diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index b2f3aea4c..2f92d6212 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -11407,7 +11407,7 @@ group="0" sex="female" name="Breast_Physics_Mass" - label="Breast Physics Mass" + label="Breast Mass" wearable="physics" edit_group="physics_advanced" value_default=".1" @@ -11420,7 +11420,7 @@ group="0" sex="female" name="Breast_Physics_Gravity" - label="Breast Physics Gravity" + label="Breast Gravity" wearable="physics" edit_group="physics_advanced" value_default="0" @@ -11434,7 +11434,7 @@ group="0" sex="female" name="Breast_Physics_Drag" - label="Breast Physics Drag" + label="Breast Drag" wearable="physics" edit_group="physics_advanced" value_default="1" @@ -11448,7 +11448,7 @@ group="0" sex="female" name="Breast_Physics_UpDown_Max_Effect" - label="Breast Physics UpDown Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_breasts_updown" value_default="0" @@ -11461,7 +11461,7 @@ group="0" sex="female" name="Breast_Physics_UpDown_Spring" - label="Breast Physics UpDown Spring" + label="Spring" wearable="physics" edit_group="physics_breasts_updown" value_default="10" @@ -11474,7 +11474,7 @@ group="0" sex="female" name="Breast_Physics_UpDown_Gain" - label="Breast Physics UpDown Gain" + label="Gain" wearable="physics" edit_group="physics_breasts_updown" value_default="10" @@ -11487,7 +11487,7 @@ group="0" sex="female" name="Breast_Physics_UpDown_Damping" - label="Breast Physics UpDown Damping" + label="Damping" wearable="physics" edit_group="physics_breasts_updown" value_default=".2" @@ -11501,7 +11501,7 @@ group="0" sex="female" name="Breast_Physics_InOut_Max_Effect" - label="Breast Physics InOut Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_breasts_inout" value_default="0" @@ -11514,7 +11514,7 @@ group="0" sex="female" name="Breast_Physics_InOut_Spring" - label="Breast Physics InOut Spring" + label="Spring" wearable="physics" edit_group="physics_breasts_inout" value_default="10" @@ -11527,7 +11527,7 @@ group="0" sex="female" name="Breast_Physics_InOut_Gain" - label="Breast Physics InOut Gain" + label="Gain" wearable="physics" edit_group="physics_breasts_inout" value_default="10" @@ -11540,7 +11540,7 @@ group="0" sex="female" name="Breast_Physics_InOut_Damping" - label="Breast Physics InOut Damping" + label="Damping" wearable="physics" edit_group="physics_breasts_inout" value_default=".2" @@ -11553,7 +11553,7 @@ id="10011" group="0" name="Belly_Physics_Mass" - label="Belly Physics Mass" + label="Belly Mass" wearable="physics" edit_group="physics_advanced" value_default=".1" @@ -11565,7 +11565,7 @@ id="10012" group="0" name="Belly_Physics_Gravity" - label="Belly Physics Gravity" + label="Belly Gravity" wearable="physics" edit_group="physics_advanced" value_default="0" @@ -11577,7 +11577,7 @@ id="10013" group="0" name="Belly_Physics_Drag" - label="Belly Physics Drag" + label="Belly Drag" wearable="physics" edit_group="physics_advanced" value_default="1" @@ -11589,7 +11589,7 @@ id="10014" group="0" name="Belly_Physics_UpDown_Max_Effect" - label="Belly Physics UpDown Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_belly_updown" value_default="0" @@ -11601,7 +11601,7 @@ id="10015" group="0" name="Belly_Physics_UpDown_Spring" - label="Belly Physics UpDown Spring" + label="Spring" wearable="physics" edit_group="physics_belly_updown" value_default="10" @@ -11613,7 +11613,7 @@ id="10016" group="0" name="Belly_Physics_UpDown_Gain" - label="Belly Physics UpDown Gain" + label="Gain" wearable="physics" edit_group="physics_belly_updown" value_default="10" @@ -11625,7 +11625,7 @@ id="10017" group="0" name="Belly_Physics_UpDown_Damping" - label="Belly Physics UpDown Damping" + label="Damping" wearable="physics" edit_group="physics_belly_updown" value_default=".2" @@ -11638,7 +11638,7 @@ id="10018" group="0" name="Butt_Physics_Mass" - label="Butt Physics Mass" + label="Butt Mass" wearable="physics" edit_group="physics_advanced" value_default=".1" @@ -11650,7 +11650,7 @@ id="10019" group="0" name="Butt_Physics_Gravity" - label="Butt Physics Gravity" + label="Butt Gravity" wearable="physics" edit_group="physics_advanced" value_default="0" @@ -11662,7 +11662,7 @@ id="10020" group="0" name="Butt_Physics_Drag" - label="Butt Physics Drag" + label="Butt Drag" wearable="physics" edit_group="physics_advanced" value_default="1" @@ -11675,7 +11675,7 @@ id="10021" group="0" name="Butt_Physics_UpDown_Max_Effect" - label="Butt Physics UpDown Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_butt_updown" value_default="0" @@ -11687,7 +11687,7 @@ id="10022" group="0" name="Butt_Physics_UpDown_Spring" - label="Butt Physics UpDown Spring" + label="Spring" wearable="physics" edit_group="physics_butt_updown" value_default="10" @@ -11699,7 +11699,7 @@ id="10023" group="0" name="Butt_Physics_UpDown_Gain" - label="Butt Physics UpDown Gain" + label="Gain" wearable="physics" edit_group="physics_butt_updown" value_default="10" @@ -11711,7 +11711,7 @@ id="10024" group="0" name="Butt_Physics_UpDown_Damping" - label="Butt Physics UpDown Damping" + label="Damping" wearable="physics" edit_group="physics_butt_updown" value_default=".2" @@ -11724,7 +11724,7 @@ id="10025" group="0" name="Butt_Physics_LeftRight_Max_Effect" - label="Butt Physics LeftRight Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_butt_leftright" value_default="0" @@ -11736,7 +11736,7 @@ id="10026" group="0" name="Butt_Physics_LeftRight_Spring" - label="Butt Physics LeftRight Spring" + label="Spring" wearable="physics" edit_group="physics_butt_leftright" value_default="10" @@ -11748,7 +11748,7 @@ id="10027" group="0" name="Butt_Physics_LeftRight_Gain" - label="Butt Physics LeftRight Gain" + label="Gain" wearable="physics" edit_group="physics_butt_leftright" value_default="10" @@ -11760,7 +11760,7 @@ id="10028" group="0" name="Butt_Physics_LeftRight_Damping" - label="Butt Physics LeftRight Damping" + label="Damping" wearable="physics" edit_group="physics_butt_leftright" value_default=".2" @@ -11774,7 +11774,7 @@ group="0" sex="female" name="Breast_Physics_LeftRight_Max_Effect" - label="Breast Physics LeftRight Max Effect" + label="Max Effect" wearable="physics" edit_group="physics_breasts_leftright" value_default="0" @@ -11787,7 +11787,7 @@ group="0" sex="female" name="Breast_Physics_LeftRight_Spring" - label="Breast Physics LeftRight Spring" + label="Spring" wearable="physics" edit_group="physics_breasts_leftright" value_default="10" @@ -11800,7 +11800,7 @@ group="0" sex="female" name="Breast_Physics_LeftRight_Gain" - label="Breast Physics LeftRight Gain" + label="Gain" wearable="physics" edit_group="physics_breasts_leftright" value_default="10" @@ -11813,7 +11813,7 @@ group="0" sex="female" name="Breast_Physics_LeftRight_Damping" - label="Breast Physics LeftRight Damping" + label="Damping" wearable="physics" edit_group="physics_breasts_leftright" value_default=".2" diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 2cc35f404..c950b8c33 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -417,7 +417,7 @@ enum ESubpart { struct LLSubpart { - LLSubpart() : mSex( SEX_BOTH ) {} + LLSubpart() : mSex( SEX_BOTH ), mVisualHint(true) {} std::string mButtonName; std::string mTargetJoint; @@ -425,6 +425,8 @@ struct LLSubpart LLVector3d mTargetOffset; LLVector3d mCameraOffset; ESex mSex; + + bool mVisualHint; }; //////////////////////////////////////////////////////////////////////////// @@ -629,7 +631,7 @@ void LLPanelEditWearable::setSubpart( ESubpart subpart ) llassert( sorted_params.find(-param->getDisplayOrder()) == sorted_params.end() ); // Check for duplicates sorted_params.insert(vt); } - gFloaterCustomize->generateVisualParamHints(NULL, sorted_params); + gFloaterCustomize->generateVisualParamHints(NULL, sorted_params, part->mVisualHint); gFloaterCustomize->updateScrollingPanelUI(); gFloaterCustomize->childSetEnabled("Export", can_export); gFloaterCustomize->childSetEnabled("Import", can_import); @@ -982,6 +984,7 @@ void LLPanelEditWearable::draw() for (std::map::iterator iter = mSubpartList.begin(); iter != mSubpartList.end(); ++iter) { + childSetVisible(iter->second->mButtonName,has_wearable); if( has_wearable && is_complete && is_modifiable ) { childSetEnabled(iter->second->mButtonName, iter->second->mSex & avatar->getSex() ); @@ -1001,6 +1004,8 @@ void LLPanelEditWearable::draw() childSetVisible("path", FALSE); + LLTextBox *av_height = getChild("avheight",FALSE,FALSE); + if(av_height) //Only display this if the element exists { // Display the shape's nominal height. // @@ -1014,8 +1019,8 @@ void LLPanelEditWearable::draw() std::ostringstream avheight(std::ostringstream::trunc); avheight << std::fixed << std::setprecision(2) << avsize << " m (" << feet << "' " << inches << "\")"; - childSetVisible("avheight", TRUE); - childSetTextArg("avheight", "[AVHEIGHT]", avheight.str()); + av_height->setVisible(TRUE); + av_height->setTextArg("[AVHEIGHT]",avheight.str()); } if(has_wearable && !is_modifiable) @@ -1279,7 +1284,7 @@ void LLPanelEditWearable::setUIPermissions(U32 perm_mask, BOOL is_complete) class LLScrollingPanelParam : public LLScrollingPanel { public: - LLScrollingPanelParam( const std::string& name, LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify ); + LLScrollingPanelParam( const std::string& name, LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, bool bVisualHint ); virtual ~LLScrollingPanelParam(); virtual void draw(); @@ -1307,6 +1312,9 @@ public: LLViewerVisualParam* mParam; LLPointer mHintMin; LLPointer mHintMax; + LLButton* mLess; + LLButton* mMore; + static S32 sUpdateDelayFrames; protected: @@ -1327,51 +1335,68 @@ const S32 PARAM_PANEL_WIDTH = 2 * (3* BTN_BORDER + PARAM_HINT_WIDTH + LLPANEL_B const S32 PARAM_PANEL_HEIGHT = 2 * BTN_BORDER + PARAM_HINT_HEIGHT + PARAM_HINT_LABEL_HEIGHT + 4 * LLPANEL_BORDER_WIDTH; LLScrollingPanelParam::LLScrollingPanelParam( const std::string& name, - LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify ) + LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, bool bVisualHint ) : LLScrollingPanel( name, LLRect( 0, PARAM_PANEL_HEIGHT, PARAM_PANEL_WIDTH, 0 ) ), mParam(param), - mAllowModify(allow_modify) + mAllowModify(allow_modify), + mLess(NULL), + mMore(NULL) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_scrolling_param.xml"); - - S32 pos_x = 2 * LLPANEL_BORDER_WIDTH; - S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + SLIDERCTRL_HEIGHT; - F32 min_weight = param->getMinWeight(); - F32 max_weight = param->getMaxWeight(); - - mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, min_weight); - pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER; - mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, max_weight ); - mHintMin->setAllowsUpdates( FALSE ); - mHintMax->setAllowsUpdates( FALSE ); - childSetValue("param slider", weightToPercent(param->getWeight())); - childSetLabelArg("param slider", "[DESC]", param->getDisplayName()); - childSetEnabled("param slider", mAllowModify); - childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this); + //Set up the slider + LLSliderCtrl *slider = getChild("param slider"); + slider->setValue(weightToPercent(param->getWeight())); + slider->setLabelArg("[DESC]", param->getDisplayName()); + slider->setEnabled(mAllowModify); + slider->setCommitCallback(LLScrollingPanelParam::onSliderMoved); + slider->setCallbackUserData(this); - // *TODO::translate - std::string min_name = param->getMinDisplayName(); - std::string max_name = param->getMaxDisplayName(); - childSetValue("min param text", min_name); - childSetValue("max param text", max_name); - - LLButton* less = getChild("less"); - if (less) + if(bVisualHint) { - less->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown ); - less->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp ); - less->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown ); - less->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD ); + S32 pos_x = 2 * LLPANEL_BORDER_WIDTH; + S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + SLIDERCTRL_HEIGHT; + F32 min_weight = param->getMinWeight(); + F32 max_weight = param->getMaxWeight(); + + mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, min_weight); + pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER; + mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, max_weight ); + + mHintMin->setAllowsUpdates( FALSE ); + mHintMax->setAllowsUpdates( FALSE ); + + // *TODO::translate + std::string min_name = param->getMinDisplayName(); + std::string max_name = param->getMaxDisplayName(); + childSetValue("min param text", min_name); + childSetValue("max param text", max_name); + mLess = getChild("less"); + mLess->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown ); + mLess->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp ); + mLess->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown ); + mLess->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD ); + + mMore = getChild("more"); + mMore->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown ); + mMore->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp ); + mMore->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown ); + mMore->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD ); } - - LLButton* more = getChild("more"); - if (more) + else { - more->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown ); - more->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp ); - more->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown ); - more->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD ); + //Kill everything that isn't the slider... + for(child_list_t::const_iterator it = getChildList()->begin();it!=getChildList()->end();) + { + if((*it)!=slider && (*it)->getName() != "panel border") + { + llinfos << "removing: " << (*it)->getName() << llendl; + removeChild((*(it++)),TRUE); + } + else ++it; + } + slider->translate(0,PARAM_HINT_HEIGHT); + reshape(getRect().getWidth(),getRect().getHeight()-PARAM_HINT_HEIGHT); } setVisible(FALSE); @@ -1386,15 +1411,19 @@ LLScrollingPanelParam::~LLScrollingPanelParam() void LLScrollingPanelParam::updatePanel(BOOL allow_modify) { - LLViewerVisualParam* param = mHintMin->getVisualParam(); - childSetValue("param slider", weightToPercent( param->getWeight() ) ); - mHintMin->requestUpdate( sUpdateDelayFrames++ ); - mHintMax->requestUpdate( sUpdateDelayFrames++ ); + childSetValue("param slider", weightToPercent( mParam->getWeight() ) ); + if(mHintMin) + mHintMin->requestUpdate( sUpdateDelayFrames++ ); + if(mHintMax) + mHintMax->requestUpdate( sUpdateDelayFrames++ ); mAllowModify = allow_modify; childSetEnabled("param slider", mAllowModify); - childSetEnabled("less", mAllowModify); - childSetEnabled("more", mAllowModify); + + if(mLess) + mLess->setEnabled(mAllowModify); + if(mMore) + mMore->setEnabled(mAllowModify); } void LLScrollingPanelParam::setVisible( BOOL visible ) @@ -1402,13 +1431,17 @@ void LLScrollingPanelParam::setVisible( BOOL visible ) if( getVisible() != visible ) { LLPanel::setVisible( visible ); - mHintMin->setAllowsUpdates( visible ); - mHintMax->setAllowsUpdates( visible ); + if(mHintMin) + mHintMin->setAllowsUpdates( visible ); + if(mHintMax) + mHintMax->setAllowsUpdates( visible ); if( visible ) { - mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ ); - mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ ); + if(mHintMin) + mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ ); + if(mHintMax) + mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ ); } } } @@ -1420,8 +1453,10 @@ void LLScrollingPanelParam::draw() return; } - childSetVisible("less", mHintMin->getVisible()); - childSetVisible("more", mHintMax->getVisible()); + if(mLess) + mLess->setVisible(mHintMin ? mHintMin->getVisible() : false); + if(mMore) + mMore->setVisible(mHintMax ? mHintMax->getVisible() : false); // Draw all the children except for the labels childSetVisible( "min param text", FALSE ); @@ -1429,25 +1464,31 @@ void LLScrollingPanelParam::draw() LLPanel::draw(); // Draw the hints over the "less" and "more" buttons. - glPushMatrix(); + if(mHintMin) { - const LLRect& r = mHintMin->getRect(); - F32 left = (F32)(r.mLeft + BTN_BORDER); - F32 bot = (F32)(r.mBottom + BTN_BORDER); - glTranslatef(left, bot, 0.f); - mHintMin->draw(); + glPushMatrix(); + { + const LLRect& r = mHintMin->getRect(); + F32 left = (F32)(r.mLeft + BTN_BORDER); + F32 bot = (F32)(r.mBottom + BTN_BORDER); + glTranslatef(left, bot, 0.f); + mHintMin->draw(); + } + glPopMatrix(); } - glPopMatrix(); - glPushMatrix(); + if(mHintMax) { - const LLRect& r = mHintMax->getRect(); - F32 left = (F32)(r.mLeft + BTN_BORDER); - F32 bot = (F32)(r.mBottom + BTN_BORDER); - glTranslatef(left, bot, 0.f); - mHintMax->draw(); + glPushMatrix(); + { + const LLRect& r = mHintMax->getRect(); + F32 left = (F32)(r.mLeft + BTN_BORDER); + F32 bot = (F32)(r.mBottom + BTN_BORDER); + glTranslatef(left, bot, 0.f); + mHintMax->draw(); + } + glPopMatrix(); } - glPopMatrix(); // Draw labels on top of the buttons @@ -1692,6 +1733,8 @@ LLFloaterCustomize::LLFloaterCustomize() mNextStepAfterSaveCallback( NULL ), mNextStepAfterSaveUserdata( NULL ) { + memset(&mWearablePanelList[0],0,sizeof(char*)*WT_COUNT); //Initialize to 0 + gSavedSettings.setU32("AvatarSex", (gAgent.getAvatarObject()->getSex() == SEX_MALE) ); mResetParams = new LLVisualParamReset(); @@ -2416,63 +2459,72 @@ void LLFloaterCustomize::initWearablePanels() } ///////////////////////////////////////// - // Alpha - panel = mWearablePanelList[WT_ALPHA]; + // Physics - if (panel) + panel = mWearablePanelList[WT_PHYSICS]; + + if(panel) { part = new LLSubpart(); - part->mTargetJoint = "mPelvis"; - part->mEditGroup = "alpha"; + part->mSex = SEX_FEMALE; + part->mTargetJoint = "mTorso"; + part->mEditGroup = "physics_breasts_updown"; part->mTargetOffset.setVec(0.f, 0.f, 0.1f); part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); - panel->addSubpart(LLStringUtil::null, SUBPART_ALPHA, part); + part->mVisualHint = false; + panel->addSubpart("Breast Bounce", SUBPART_PHYSICS_BREASTS_UPDOWN, part); - panel->addTextureDropTarget(TEX_LOWER_ALPHA, "Lower Alpha", - LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), - TRUE); - panel->addTextureDropTarget(TEX_UPPER_ALPHA, "Upper Alpha", - LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), - TRUE); - panel->addTextureDropTarget(TEX_HEAD_ALPHA, "Head Alpha", - LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), - TRUE); - panel->addTextureDropTarget(TEX_EYES_ALPHA, "Eye Alpha", - LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), - TRUE); - panel->addTextureDropTarget(TEX_HAIR_ALPHA, "Hair Alpha", - LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), - TRUE); + part = new LLSubpart(); + part->mSex = SEX_FEMALE; + part->mTargetJoint = "mTorso"; + part->mEditGroup = "physics_breasts_inout"; + part->mTargetOffset.setVec(0.f, 0.f, 0.1f); + part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); + part->mVisualHint = false; + panel->addSubpart("Breast Cleavage", SUBPART_PHYSICS_BREASTS_INOUT, part); - panel->addInvisibilityCheckbox(TEX_LOWER_ALPHA, "lower alpha texture invisible"); - panel->addInvisibilityCheckbox(TEX_UPPER_ALPHA, "upper alpha texture invisible"); - panel->addInvisibilityCheckbox(TEX_HEAD_ALPHA, "head alpha texture invisible"); - panel->addInvisibilityCheckbox(TEX_EYES_ALPHA, "eye alpha texture invisible"); - panel->addInvisibilityCheckbox(TEX_HAIR_ALPHA, "hair alpha texture invisible"); - } + part = new LLSubpart(); + part->mSex = SEX_FEMALE; + part->mTargetJoint = "mTorso"; + part->mEditGroup = "physics_breasts_leftright"; + part->mTargetOffset.setVec(0.f, 0.f, 0.1f); + part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); + part->mVisualHint = false; + panel->addSubpart("Breast Sway", SUBPART_PHYSICS_BREASTS_LEFTRIGHT, part); - ///////////////////////////////////////// - // Tattoo - panel = mWearablePanelList[WT_TATTOO]; + part = new LLSubpart(); + part->mSex = SEX_FEMALE; + part->mTargetJoint = "mTorso"; + part->mEditGroup = "physics_belly_updown"; + part->mTargetOffset.setVec(0.f, 0.f, 0.1f); + part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); + part->mVisualHint = false; + panel->addSubpart("Belly Bounce", SUBPART_PHYSICS_BELLY_UPDOWN, part); - if (panel) - { part = new LLSubpart(); part->mTargetJoint = "mPelvis"; - part->mEditGroup = "tattoo"; + part->mEditGroup = "physics_butt_updown"; part->mTargetOffset.setVec(0.f, 0.f, 0.1f); part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); - panel->addSubpart(LLStringUtil::null, SUBPART_TATTOO, part); + part->mVisualHint = false; + panel->addSubpart("Butt Bounce", SUBPART_PHYSICS_BUTT_UPDOWN, part); + + part = new LLSubpart(); + part->mTargetJoint = "mPelvis"; + part->mEditGroup = "physics_butt_leftright"; + part->mTargetOffset.setVec(0.f, 0.f, 0.1f); + part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); + part->mVisualHint = false; + panel->addSubpart("Butt Sway", SUBPART_PHYSICS_BUTT_LEFTRIGHT, part); + + part = new LLSubpart(); + part->mTargetJoint = "mTorso"; + part->mEditGroup = "physics_advanced"; + part->mTargetOffset.setVec(0.f, 0.f, 0.1f); + part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f); + part->mVisualHint = false; + panel->addSubpart("Advanced Parameters", SUBPART_PHYSICS_ADVANCED, part); - panel->addTextureDropTarget(TEX_LOWER_TATTOO, "Lower Tattoo", - LLUUID::null, - TRUE); - panel->addTextureDropTarget(TEX_UPPER_TATTOO, "Upper Tattoo", - LLUUID::null, - TRUE); - panel->addTextureDropTarget(TEX_HEAD_TATTOO, "Head Tattoo", - LLUUID::null, - TRUE); } } @@ -2607,7 +2659,7 @@ void LLFloaterCustomize::clearScrollingPanelList() } } -void LLFloaterCustomize::generateVisualParamHints(LLViewerJointMesh* joint_mesh, LLFloaterCustomize::param_map& params) +void LLFloaterCustomize::generateVisualParamHints(LLViewerJointMesh* joint_mesh, LLFloaterCustomize::param_map& params, bool bVisualHint) { // sorted_params is sorted according to magnitude of effect from // least to greatest. Adding to the front of the child list @@ -2618,7 +2670,7 @@ void LLFloaterCustomize::generateVisualParamHints(LLViewerJointMesh* joint_mesh, param_map::iterator end = params.end(); for(param_map::iterator it = params.begin(); it != end; ++it) { - mScrollingPanelList->addPanel( new LLScrollingPanelParam( "LLScrollingPanelParam", joint_mesh, (*it).second.second, (*it).second.first) ); + mScrollingPanelList->addPanel( new LLScrollingPanelParam( "LLScrollingPanelParam", joint_mesh, (*it).second.second, (*it).second.first, bVisualHint) ); } } } diff --git a/indra/newview/llfloatercustomize.h b/indra/newview/llfloatercustomize.h index 5648cc6af..ceb49af01 100644 --- a/indra/newview/llfloatercustomize.h +++ b/indra/newview/llfloatercustomize.h @@ -88,7 +88,7 @@ public: // New methods void clearScrollingPanelList(); void generateVisualParamHints(LLViewerJointMesh* joint_mesh, - param_map& params); + param_map& params, bool bVisualHint); const std::string& getEditGroup(); void updateScrollingPanelList(BOOL allow_modify); diff --git a/indra/newview/skins/default/xui/en-us/floater_customize.xml b/indra/newview/skins/default/xui/en-us/floater_customize.xml index 2dea4626a..261ab3189 100644 --- a/indra/newview/skins/default/xui/en-us/floater_customize.xml +++ b/indra/newview/skins/default/xui/en-us/floater_customize.xml @@ -1298,11 +1298,103 @@ scratch and wear it.