diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index fd08df02d800880f47c9e5aaafbe03689d6bf903..18b15e08c4c89b3f62ce36d3cb4c9621f0110d72 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -134,6 +134,21 @@ BOOL LLVector3::clampLength( F32 length_limit )
 	return changed;
 }
 
+BOOL LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec)
+{
+	BOOL ret = FALSE;
+
+	if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = TRUE; }
+	if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = TRUE; }
+	if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = TRUE; }
+
+	if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = TRUE; }
+	if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = TRUE; }
+	if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = TRUE; }
+
+	return ret;
+}
+
 
 // Sets all values to absolute value of their original values
 // Returns TRUE if data changed
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index ef002fe9f2b53574d75081b74c4d983a73f092d6..4b3efe739407f3e2b4e51a76a8d616de46f6b42a 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -69,6 +69,7 @@ class LLVector3
 
 		inline BOOL isFinite() const;									// checks to see if all values of LLVector3 are finite
 		BOOL		clamp(F32 min, F32 max);		// Clamps all values to (min,max), returns TRUE if data changed
+		BOOL		clamp(const LLVector3 &min_vec, const LLVector3 &max_vec); // Scales vector by another vector
 		BOOL		clampLength( F32 length_limit );					// Scales vector to limit length to a value
 
 		void		quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz);	// changes the vector to reflect quatization
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 243023e468374db5df6b09b5c7dbc342669777d7..32d3a31786f6fbe421e1d352cc73e46f8479b7ea 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -380,6 +380,7 @@ set(viewer_SOURCE_FILES
     llparcelselection.cpp
     llparticipantlist.cpp
     llpatchvertexarray.cpp
+    llphysicsmotion.cpp
     llplacesinventorybridge.cpp
     llplacesinventorypanel.cpp
     llpopupview.cpp
@@ -402,6 +403,7 @@ set(viewer_SOURCE_FILES
     llscreenchannel.cpp
     llscriptfloater.cpp
     llscrollingpanelparam.cpp
+    llscrollingpanelparambase.cpp
     llsearchcombobox.cpp
     llsearchhistory.cpp
     llsecapi.cpp
@@ -915,6 +917,7 @@ set(viewer_HEADER_FILES
     llparcelselection.h
     llparticipantlist.h
     llpatchvertexarray.h
+    llphysicsmotion.h
     llplacesinventorybridge.h
     llplacesinventorypanel.h
     llpolymesh.h
@@ -939,6 +942,7 @@ set(viewer_HEADER_FILES
     llscreenchannel.h
     llscriptfloater.h
     llscrollingpanelparam.h
+    llscrollingpanelparambase.h
     llsearchcombobox.h
     llsearchhistory.h
     llsecapi.h
diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml
index 4da2b0fd0014a31759bc1c819df9e99783ce55c1..4e137d971a6635f6ceafab8437569850bee3e1ef 100644
--- a/indra/newview/app_settings/high_graphics.xml
+++ b/indra/newview/app_settings/high_graphics.xml
@@ -4,6 +4,8 @@
 	<RenderAvatarCloth value="FALSE"/>
 	<!--Default for now-->
 	<RenderAvatarLODFactor value="1.0"/>
+  <!--Default for now-->
+  <RenderAvatarPhysicsLODFactor value="0.9"/>
 	<!--NO SHADERS-->
 	<RenderAvatarVP value="TRUE"/>
 	<!--Short Range-->
diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml
index 136087f69b81d0a2817de0d3d8d8cbb3618382fa..79463b475c4ca010a5ed25499d1cc8a0586aea3d 100644
--- a/indra/newview/app_settings/low_graphics.xml
+++ b/indra/newview/app_settings/low_graphics.xml
@@ -5,6 +5,8 @@
 	<!--Default for now-->
 	<RenderAvatarLODFactor value="0.5"/>
   <!--Default for now-->
+  <RenderAvatarPhysicsLODFactor value="0.0"/>
+  <!--Default for now-->
   <RenderAvatarMaxVisible value="3"/>
 	<!--NO SHADERS-->
 	<RenderAvatarVP value="FALSE"/>
diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml
index c150a87cdf92d97f4a22331eb9e70c3ad62336db..ab1e2a2e1ca2fecba46d70ca766eaa26c787c152 100644
--- a/indra/newview/app_settings/mid_graphics.xml
+++ b/indra/newview/app_settings/mid_graphics.xml
@@ -4,6 +4,8 @@
 	<RenderAvatarCloth value="FALSE"/>
 	<!--Default for now-->
 	<RenderAvatarLODFactor value="0.5"/>
+  <!--Default for now-->
+  <RenderAvatarPhysicsLODFactor value="0.75"/>
 	<!--NO SHADERS-->
 	<RenderAvatarVP value="TRUE"/>
 	<!--Short Range-->
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 14f1b3c4baeb2d71990299287d96c0e9ef7efdfb..dd85c5cb866f3a7e6b017fb84efa2fe7448eb4ac 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -641,7 +641,28 @@
       <key>Value</key>
       <integer>10</integer>
     </map>
-
+    <key>AvatarPhysics</key>
+    <map>
+      <key>Comment</key>
+      <string>Enable avatar physics.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+  <key>AvatarPhysicsTest</key>
+  <map>
+    <key>Comment</key>
+    <string>Simulate continuous physics behavior on all nearby avatars.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
     <key>AvatarSex</key>
     <map>
       <key>Comment</key>
@@ -653,6 +674,7 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+
     <key>BackgroundYieldTime</key>
     <map>
       <key>Comment</key>
@@ -6800,6 +6822,17 @@
       <key>Value</key>
       <integer>12</integer>
     </map>
+    <key>RenderAvatarPhysicsLODFactor</key>
+    <map>
+      <key>Comment</key>
+      <string>Controls level of detail of avatar physics (such as breast physics).</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <integer>1.0</integer>
+    </map>
     <key>RenderAvatarVP</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml
index e7dce3b9896d749a5c2100fbc798e92429170a3a..e1f3ca5769995e5b7327c54b964b317a4a994f6c 100644
--- a/indra/newview/app_settings/ultra_graphics.xml
+++ b/indra/newview/app_settings/ultra_graphics.xml
@@ -4,6 +4,8 @@
 	<RenderAvatarCloth value="TRUE"/>
 	<!--Default for now-->
 	<RenderAvatarLODFactor value="1.0"/>
+  <!--Default for now-->
+  <RenderAvatarPhysicsLODFactor value="1.0"/>
 	<!--NO SHADERS-->
 	<RenderAvatarVP value="TRUE"/>
 	<!--Short Range-->
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index a9b4ff02c5a872280149aed393dee873a4db3c11..4585ba658c04677e6b1e8b6b5ec331efad517f7c 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -612,7 +612,7 @@
      id="36"
      group="0"
      name="Shoulders"
-   label="Shoulders"
+     label="Shoulders"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="4"
@@ -4040,26 +4040,6 @@
           scale="0.0 0.0 0.01"
           pos="0 0 -0.01"/>
       </param_morph>
-
-    </param>
-
-    <param
-     id="507"
-     group="0"
-     sex="female"
-     name="Breast_Gravity"
-     label="Breast Buoyancy"
-     wearable="shape"
-     edit_group="shape_torso"
-     edit_group_order="7"
-     label_min="Less Gravity"
-     label_max="More Gravity"
-     value_default="0"
-     value_min="-1.5"
-     value_max="2"
-     camera_elevation=".3"
-     camera_distance=".8">
-      <param_morph />
     </param>
 
     <param
@@ -4112,25 +4092,6 @@
       </param_morph>
     </param>
 
-    <param
-     id="684"
-     group="0"
-     sex="female"
-     name="Breast_Female_Cleavage"
-     label="Breast Cleavage"
-     wearable="shape"
-     edit_group="shape_torso"
-     edit_group_order="8"
-     label_min="Separate"
-     label_max="Join"
-     value_default="0"
-     value_min="-.3"
-     value_max="1.3"
-     camera_elevation=".3"
-     camera_distance=".8">
-      <param_morph />
-    </param>
-
     <param
      id="685"
      group="0"
@@ -4327,9 +4288,53 @@
       <param_morph />
     </param>
 
+    <!--
+            #############
+            # physics morphs (not user controlled)
+            #############
+            -->
+    <param
+     id="1200"
+     group="1"
+     sex="female"
+     name="Breast_Gravity"
+     wearable="shape"
+     edit_group="driven"
+     value_default="0"
+     value_min="-1.5"
+     value_max="2">
+      <param_morph />
+    </param>
+
+    <param
+     id="1201"
+     group="1"
+     sex="female"
+     name="Breast_Female_Cleavage"
+     wearable="shape"
+     edit_group="driven"
+     value_default="0"
+     value_min="-.3"
+     value_max="1.3">
+      <param_morph />
+    </param>
+
+    <param
+     id="1204"
+     group="1"
+     name="Belly_Physics_Torso_UpDown_Driven"
+     wearable="physics"
+     edit_group="driven"
+     value_default="0"
+     value_min="-1"
+     value_max="1">
+      <param_morph />
+    </param>
+
     <!--
          #end morph targets
           -->
+
   </mesh>
 
   <mesh
@@ -4390,6 +4395,7 @@
       <param_morph />
     </param>
 
+
     <param
      id="151"
      group="1"
@@ -4828,9 +4834,50 @@
       <param_morph />
     </param>
 
+    <!--
+            #############
+            # physics morphs (not user controlled)
+            #############
+            -->
+    <param
+     id="1202"
+     group="1"
+     name="Belly_Physics_Legs_UpDown_Driven"
+     wearable="physics"
+     edit_group="driven"
+     value_min="-1"
+     value_max="1">
+      <param_morph />
+    </param>
+
+
+    <param
+     id="1205"
+     group="1"
+     name="Butt_Physics_UpDown_Driven"
+     wearable="physics"
+     edit_group="driven"
+     value_default="0">
+      <param_morph />
+    </param>
+
+    <param
+     id="1206"
+     group="1"
+     name="Butt_Physics_LeftRight_Driven"
+     wearable="physics"
+     edit_group="driven"
+     value_default="0"
+     value_min="-2"
+     value_max="2">
+      <param_morph />
+    </param>
+
+
     <!--
             #end morph targets
             -->
+
   </mesh>
 
   <mesh
@@ -9074,12 +9121,13 @@ render_pass="bump">
 
   <!-- =========================================================== -->
   <driver_parameters>
+
     <param
      id="828"
      group="0"
      name="Loose Upper Clothing"
      label="Shirt Fit"
-   show_simple="true"
+	 show_simple="true"
      wearable="shirt"
      edit_group="shirt"
      edit_group_order="4"
@@ -11631,6 +11679,524 @@ render_pass="bump">
       </param_driver>
     </param>
 
+  <!-- ==PHYSICS PARAMETERS======================================= -->
+
+   <param
+     id="507"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Controller"
+     label="Breast Physics UpDown Controller"
+     wearable="shape"
+     edit_group="shape_torso"
+     edit_group_order="7"
+     value_default="0"
+     value_min="-1.5"
+     value_max="2"
+     camera_elevation=".3"
+     camera_distance=".8">
+      <param_driver>
+        <driven
+         id="1200" />
+	</param_driver>
+    </param>
+
+   <param
+     id="684"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Controller"
+     label="Breast Physics InOut Controller"
+     wearable="shape"
+     edit_group="shape_torso"
+     edit_group_order="8"
+     value_default="0"
+     value_min="-.3"
+     value_max="1.3">
+      <param_driver>
+        <driven
+         id="1201" />
+	</param_driver>
+    </param>
+
+    <param
+     id="1120"
+     group="1"
+     wearable="physics"
+     name="Belly_Physics_UpDown_Controller"
+     label="Belly Physics UpDown Controller"
+     value_min="-1"
+     value_max="1"
+     value_default="0">
+      <param_driver>
+        <driven
+         id="1202" />
+        <driven
+         id="1203" />
+        <driven
+         id="1204" />
+      </param_driver>
+    </param>
+
+    <param
+     id="1100"
+     group="1"
+     wearable="shape"
+     name="Butt_Physics_UpDown_Controller"
+     label="Butt Physics UpDown Controller"
+     value_min="-1"
+     value_max="1"
+     value_default="0">
+      <param_driver>
+        <driven
+         id="1205" />
+      </param_driver>
+    </param>
+
+    <param
+     id="1101"
+     group="1"
+     wearable="shape"
+     name="Butt_Physics_LeftRight_Controller"
+     label="Butt Physics LeftRight Controller"
+     value_min="-1"
+     value_max="1"
+     value_default="0">
+      <param_driver>
+        <driven
+         id="1206" />
+      </param_driver>
+    </param>
+
+    <param
+     id="1110"
+     group="0"
+     sex="female"
+     name="Breast_Physics_Mass"
+     label="Breast Physics Mass"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".1"
+     value_min=".1"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1111"
+     group="0"
+     sex="female"
+     name="Breast_Physics_Smoothing"
+     label="Breast Physics Smoothing"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="2"
+     value_min="1"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1112"
+     group="0"
+     sex="female"
+     name="Breast_Physics_Gravity"
+     label="Breast Physics Gravity"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="0"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+
+   <param
+     id="1113"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Max_Velocity"
+     label="Breast Physics UpDown Max Speed"
+     wearable="physics"
+     edit_group="physics_breasts_updown"
+     value_default="0"
+     value_min="0"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1114"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Spring"
+     label="Breast Physics UpDown Spring"
+     wearable="physics"
+     edit_group="physics_breasts_updown"
+     value_default=".1"
+     value_min="0"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1115"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Gain"
+     label="Breast Physics UpDown Gain"
+     wearable="physics"
+     edit_group="physics_breasts_updown"
+     value_default="10"
+     value_min="1"
+     value_max="100">
+	 <param_driver />
+    </param>
+    <param
+     id="1116"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Damping"
+     label="Breast Physics UpDown Damping"
+     wearable="physics"
+     edit_group="physics_breasts_updown"
+     value_default=".05"
+     value_min="0"
+     value_max=".1"
+     camera_elevation=".3"
+     camera_distance=".8">
+	 <param_driver />
+    </param>
+   <param
+     id="1117"
+     group="0"
+     sex="female"
+     name="Breast_Physics_UpDown_Drag"
+     label="Breast Physics UpDown Drag"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".15"
+     value_min="0"
+     value_max=".5">
+	 <param_driver />
+    </param>
+
+   <param
+     id="1118"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Max_Velocity"
+     label="Breast Physics InOut Max Speed"
+     wearable="physics"
+     edit_group="physics_breasts_inout"
+     value_default="0"
+     value_min="0"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1119"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Spring"
+     label="Breast Physics InOut Spring"
+     wearable="physics"
+     edit_group="physics_breasts_inout"
+     value_default=".1"
+     value_min="0"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1120"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Gain"
+     label="Breast Physics InOut Gain"
+     wearable="physics"
+     edit_group="physics_breasts_inout"
+     value_default="10"
+     value_min="1"
+     value_max="100">
+	 <param_driver />
+    </param>
+    <param
+     id="1121"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Damping"
+     label="Breast Physics InOut Damping"
+     wearable="physics"
+     edit_group="physics_breasts_inout"
+     value_default=".05"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1122"
+     group="0"
+     sex="female"
+     name="Breast_Physics_InOut_Drag"
+     label="Breast Physics InOut Drag"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".15"
+     value_min="0"
+     value_max=".5">
+	 <param_driver />
+    </param>
+
+    <param
+     id="1130"
+     group="0"
+     name="Belly_Physics_Mass"
+     label="Belly Physics Mass"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".1"
+     value_min=".1"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1131"
+     group="0"
+     name="Belly_Physics_Smoothing"
+     label="Belly Physics Smoothing"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="2"
+     value_min="1"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1132"
+     group="0"
+     name="Belly_Physics_Gravity"
+     label="Belly Physics Gravity"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="0"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1133"
+     group="0"
+     name="Belly_Physics_UpDown_Max_Velocity"
+     label="Belly Physics UpDown Max Speed"
+     wearable="physics"
+     edit_group="physics_belly_updown"
+     value_default="0"
+     value_min="0"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1134"
+     group="0"
+     name="Belly_Physics_UpDown_Spring"
+     label="Belly Physics UpDown Spring"
+     wearable="physics"
+     edit_group="physics_belly_updown"
+     value_default=".1"
+     value_min="0"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1135"
+     group="0"
+     name="Belly_Physics_UpDown_Gain"
+     label="Belly Physics UpDown Gain"
+     wearable="physics"
+     edit_group="physics_belly_updown"
+     value_default="10"
+     value_min="1"
+     value_max="100">
+	 <param_driver />
+    </param>
+    <param
+     id="1136"
+     group="0"
+     name="Belly_Physics_UpDown_Damping"
+     label="Belly Physics UpDown Damping"
+     wearable="physics"
+     edit_group="physics_belly_updown"
+     value_default=".05"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1137"
+     group="0"
+     name="Belly_Physics_UpDown_Drag"
+     label="Belly Physics UpDown Drag"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".15"
+     value_min="0"
+     value_max=".5">
+	 <param_driver />
+    </param>
+
+    <param
+     id="1140"
+     group="0"
+     name="Butt_Physics_Mass"
+     label="Butt Physics Mass"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".1"
+     value_min=".1"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1141"
+     group="0"
+     name="Butt_Physics_Smoothing"
+     label="Butt Physics Smoothing"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="2"
+     value_min="1"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1142"
+     group="0"
+     name="Butt_Physics_Gravity"
+     label="Butt Physics Gravity"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default="0"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1143"
+     group="0"
+     name="Butt_Physics_UpDown_Max_Velocity"
+     label="Butt Physics UpDown Max Speed"
+     wearable="physics"
+     edit_group="physics_butt_updown"
+     value_default="0"
+     value_min="0"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1144"
+     group="0"
+     name="Butt_Physics_UpDown_Spring"
+     label="Butt Physics UpDown Spring"
+     wearable="physics"
+     edit_group="physics_butt_updown"
+     value_default=".1"
+     value_min="0"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1145"
+     group="0"
+     name="Butt_Physics_UpDown_Gain"
+     label="Butt Physics UpDown Gain"
+     wearable="physics"
+     edit_group="physics_butt_updown"
+     value_default="10"
+     value_min="1"
+     value_max="100">
+	 <param_driver />
+    </param>
+    <param
+     id="1146"
+     group="0"
+     name="Butt_Physics_UpDown_Damping"
+     label="Butt Physics UpDown Damping"
+     wearable="physics"
+     edit_group="physics_butt_updown"
+     value_default=".05"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1147"
+     group="0"
+     name="Butt_Physics_UpDown_Drag"
+     label="Butt Physics UpDown Drag"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".15"
+     value_min="0"
+     value_max=".5">
+	 <param_driver />
+    </param>
+
+   <param
+     id="1148"
+     group="0"
+     name="Butt_Physics_LeftRight_Max_Velocity"
+     label="Butt Physics LeftRight Max Speed"
+     wearable="physics"
+     edit_group="physics_butt_leftright"
+     value_default="0"
+     value_min="0"
+     value_max="10">
+	 <param_driver />
+    </param>
+    <param
+     id="1149"
+     group="0"
+     name="Butt_Physics_LeftRight_Spring"
+     label="Butt Physics LeftRight Spring"
+     wearable="physics"
+     edit_group="physics_butt_leftright"
+     value_default=".1"
+     value_min="0"
+     value_max="1">
+	 <param_driver />
+    </param>
+    <param
+     id="1150"
+     group="0"
+     name="Butt_Physics_LeftRight_Gain"
+     label="Butt Physics LeftRight Gain"
+     wearable="physics"
+     edit_group="physics_butt_leftright"
+     value_default="10"
+     value_min="1"
+     value_max="100">
+	 <param_driver />
+    </param>
+    <param
+     id="1151"
+     group="0"
+     name="Butt_Physics_LeftRight_Damping"
+     label="Butt Physics LeftRight Damping"
+     wearable="physics"
+     edit_group="physics_butt_leftright"
+     value_default=".05"
+     value_min="0"
+     value_max=".1">
+	 <param_driver />
+    </param>
+   <param
+     id="1152"
+     group="0"
+     name="Butt_Physics_LeftRight_Drag"
+     label="Butt Physics LeftRight Drag"
+     wearable="physics"
+     edit_group="physics_advanced"
+     value_default=".15"
+     value_min="0"
+     value_max=".5">
+	 <param_driver />
+    </param>
+
 
   </driver_parameters>
 
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index a82c3da4c568abf85d2f27034668ec0b7dc050d5..15ad330418367ac7853017f229028fafd97e25e0 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -26,6 +26,7 @@ list all
 RenderAnisotropic			1	1
 RenderAvatarCloth			1	1
 RenderAvatarLODFactor		1	1.0
+RenderAvatarPhysicsLODFactor 1	1.0
 RenderAvatarMaxVisible      1   12
 RenderAvatarVP				1	1
 RenderCubeMap				1	1
@@ -71,6 +72,7 @@ list Low
 RenderAnisotropic			1	0
 RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	0
+RenderAvatarPhysicsLODFactor 1	0
 RenderAvatarMaxVisible      1   3
 RenderAvatarVP				1	0
 RenderFarClip				1	64
@@ -101,6 +103,7 @@ list Mid
 RenderAnisotropic			1	0
 RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	0.5
+RenderAvatarPhysicsLODFactor 1	0.75
 RenderAvatarVP				1	1
 RenderFarClip				1	96
 RenderFlexTimeFactor		1	1.0
@@ -129,6 +132,7 @@ list High
 RenderAnisotropic			1	1
 RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	1.0
+RenderAvatarPhysicsLODFactor 1	0.9
 RenderAvatarVP				1	1
 RenderFarClip				1	128
 RenderFlexTimeFactor		1	1.0
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 055be4cae28a0a75e03a6e2cad1bde6c028bf308..d426afb17cc23af8b547dea7f1631cd63d5bbadb 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -821,7 +821,7 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index)
 	}
 }
 
-U32	LLAgentWearables::getWearableIndex(LLWearable *wearable)
+U32	LLAgentWearables::getWearableIndex(const LLWearable *wearable) const
 {
 	if (wearable == NULL)
 	{
@@ -2045,8 +2045,9 @@ void LLAgentWearables::editWearable(const LLUUID& item_id)
 		return;
 	}
 
+	const BOOL disable_camera_switch = LLWearableType::getDisableCameraSwitch(wearable->getType());
 	LLPanel* panel = LLSideTray::getInstance()->getPanel("sidepanel_appearance");
-	LLSidepanelAppearance::editWearable(wearable, panel);
+	LLSidepanelAppearance::editWearable(wearable, panel, disable_camera_switch);
 }
 
 // Request editing the item after it gets worn.
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index d7e77a5a5bd9a323e53a6fb8fbbd0941d42ed0af..3ef50f14da45b8c13e844004a2e748adb7bdd2fe 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -124,7 +124,7 @@ public:
 	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove);
 	void			setWearableName(const LLUUID& item_id, const std::string& new_name);
 	void			addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index);
-	U32				getWearableIndex(LLWearable *wearable);
+	U32				getWearableIndex(const LLWearable *wearable) const;
 
 protected:
 	void			setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f6fe7ecd012b353e769dc34fc7e0c1b4c452ac48..cfb5853cfd80a1b11c0442e3f80ab765df54d328 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -498,6 +498,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				= (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
 	LLVOAvatar::sVisibleInFirstPerson	= gSavedSettings.getBOOL("FirstPersonAvatarVisible");
 	// clamp auto-open time to some minimum usable value
diff --git a/indra/newview/llbreastmotion.cpp b/indra/newview/llbreastmotion.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7c205a8b9f39aae568275854270647cc34008a0d
--- /dev/null
+++ b/indra/newview/llbreastmotion.cpp
@@ -0,0 +1,402 @@
+/** 
+ * @file llbreastmotion.cpp
+ * @brief Implementation of LLBreastMotion 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 "llbreastmotion.h"
+#include "llcharacter.h"
+#include "llviewercontrol.h"
+#include "llviewervisualparam.h"
+#include "llvoavatarself.h"
+
+#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
+
+#define N_PARAMS 2
+
+// User-set params
+static const std::string breast_param_names_user[N_PARAMS] =
+{
+	"Breast_Female_Cleavage_Driver",
+	"Breast_Gravity_Driver"
+};
+
+// Params driven by this algorithm
+static const std::string breast_param_names_driven[N_PARAMS] =
+{
+	"Breast_Female_Cleavage",
+	"Breast_Gravity"
+};
+
+
+
+LLBreastMotion::LLBreastMotion(const LLUUID &id) : 
+	LLMotion(id),
+	mCharacter(NULL)
+{
+	mName = "breast_motion";
+	mChestState = new LLJointState;
+
+	mBreastMassParam = (F32)1.0;
+	mBreastDragParam = LLVector3((F32)0.1, (F32)0.1, (F32)0.1);
+	mBreastSmoothingParam = (U32)2;
+	mBreastGravityParam = (F32)0.0;
+
+	mBreastSpringParam = LLVector3((F32)3.0, (F32)0.0, (F32)3.0);
+	mBreastGainParam = LLVector3((F32)50.0, (F32)0.0, (F32)50.0);
+	mBreastDampingParam = LLVector3((F32)0.3, (F32)0.0, (F32)0.3);
+	mBreastMaxVelocityParam = LLVector3((F32)10.0, (F32)0.0, (F32)10.0);
+
+	mBreastParamsUser[0] = mBreastParamsUser[1] = mBreastParamsUser[2] = NULL;
+	mBreastParamsDriven[0] = mBreastParamsDriven[1] = mBreastParamsDriven[2] = NULL;
+
+	mCharLastPosition_world_pt = LLVector3(0,0,0);
+	mCharLastVelocity_local_vec = LLVector3(0,0,0);
+	mCharLastAcceleration_local_vec = LLVector3(0,0,0);
+	mBreastLastPosition_local_pt = LLVector3(0,0,0);
+	mBreastLastUpdatePosition_local_pt = LLVector3(0,0,0);
+	mBreastVelocity_local_vec = LLVector3(0,0,0);
+}
+
+LLBreastMotion::~LLBreastMotion()
+{
+}
+
+BOOL LLBreastMotion::onActivate() 
+{ 
+	return TRUE; 
+}
+
+void LLBreastMotion::onDeactivate() 
+{
+}
+
+LLMotion::LLMotionInitStatus LLBreastMotion::onInitialize(LLCharacter *character)
+{
+	mCharacter = character;
+
+	if (!mChestState->setJoint(character->getJoint("mChest")))
+	{
+		return STATUS_FAILURE;
+	}
+
+	mChestState->setUsage(LLJointState::ROT);
+	addJointState( mChestState );
+	
+	for (U32 i=0; i < N_PARAMS; i++)
+	{
+		mBreastParamsUser[i] = NULL;
+		mBreastParamsDriven[i] = NULL;
+		mBreastParamsMin[i] = 0;
+		mBreastParamsMax[i] = 0;
+		if (breast_param_names_user[i] != "" && breast_param_names_driven[i] != "")
+		{
+			mBreastParamsUser[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_user[i].c_str());
+			mBreastParamsDriven[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_driven[i].c_str());
+			if (mBreastParamsDriven[i])
+			{
+				mBreastParamsMin[i] = mBreastParamsDriven[i]->getMinWeight();
+				mBreastParamsMax[i] = mBreastParamsDriven[i]->getMaxWeight();
+			}
+		}
+	}
+	
+	mTimer.reset();
+	return STATUS_SUCCESS;
+}
+
+F32 LLBreastMotion::getMinPixelArea() 
+{
+	return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION;
+}
+	
+
+F32 LLBreastMotion::calculateTimeDelta()
+{
+	const F32 time = mTimer.getElapsedTimeF32();
+	const F32 time_delta = time - mLastTime;
+	mLastTime = time;
+	return time_delta;
+}
+
+// Local space means "parameter space".
+LLVector3 LLBreastMotion::toLocal(const LLVector3 &world_vector)
+{
+	LLVector3 local_vec(0,0,0);
+
+	LLJoint *chest_joint = mChestState->getJoint();
+	const LLQuaternion world_rot = chest_joint->getWorldRotation();
+	
+	// Cleavage
+	LLVector3 breast_dir_world_vec = LLVector3(-1,0,0) * world_rot; // -1 b/c cleavage param changes opposite to direction
+	breast_dir_world_vec.normalize();
+	local_vec[0] = world_vector * breast_dir_world_vec;
+	
+	// Up-Down Bounce
+	LLVector3 breast_up_dir_world_vec = LLVector3(0,0,1) * world_rot;
+	breast_up_dir_world_vec.normalize();
+	local_vec[1] = world_vector * breast_up_dir_world_vec;
+
+	return local_vec;
+}
+
+LLVector3 LLBreastMotion::calculateVelocity_local(const F32 time_delta)
+{
+	LLJoint *chest_joint = mChestState->getJoint();
+	const LLVector3 world_pos_pt = chest_joint->getWorldPosition();
+	const LLQuaternion world_rot = chest_joint->getWorldRotation();
+	const LLVector3 last_world_pos_pt = mCharLastPosition_world_pt;
+	const LLVector3 char_velocity_world_vec = (world_pos_pt-last_world_pos_pt) / time_delta;
+	const LLVector3 char_velocity_local_vec = toLocal(char_velocity_world_vec);
+
+	return char_velocity_local_vec;
+}
+
+LLVector3 LLBreastMotion::calculateAcceleration_local(const LLVector3 &new_char_velocity_local_vec,
+													  const F32 time_delta)
+{
+	LLVector3 char_acceleration_local_vec = new_char_velocity_local_vec - mCharLastVelocity_local_vec;
+	
+	char_acceleration_local_vec = 
+		char_acceleration_local_vec * 1.0/mBreastSmoothingParam + 
+		mCharLastAcceleration_local_vec * (mBreastSmoothingParam-1.0)/mBreastSmoothingParam;
+
+	mCharLastAcceleration_local_vec = char_acceleration_local_vec;
+
+	return char_acceleration_local_vec;
+}
+
+BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask)
+{
+	// Skip if disabled globally.
+	if (!gSavedSettings.getBOOL("AvatarPhysics"))
+	{
+		return TRUE;
+	}
+
+	// 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;
+	}
+	
+	if (mCharacter->getSex() != SEX_FEMALE) return TRUE;
+	const F32 time_delta = calculateTimeDelta();
+	if (time_delta < .01 || time_delta > 10.0) return TRUE;
+
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Get all parameters and settings
+	//
+
+	mBreastMassParam = mCharacter->getVisualParamWeight("Breast_Physics_Mass");
+	mBreastSmoothingParam = (U32)(mCharacter->getVisualParamWeight("Breast_Physics_Smoothing"));
+	mBreastGravityParam = mCharacter->getVisualParamWeight("Breast_Physics_Gravity");
+
+	mBreastSpringParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Spring");
+	mBreastGainParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Gain");
+	mBreastDampingParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Damping");
+	mBreastMaxVelocityParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Max_Velocity");
+	mBreastDragParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Drag");
+
+	mBreastSpringParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Spring");
+	mBreastGainParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Gain");
+	mBreastDampingParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Damping");
+	mBreastMaxVelocityParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Max_Velocity");
+	mBreastDragParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Drag");
+
+
+	// Get the current morph parameters.
+	LLVector3 breast_user_local_pt(0,0,0);
+	for (U32 i=0; i < N_PARAMS; i++)
+	{
+		if (mBreastParamsUser[i] != NULL)
+		{
+			breast_user_local_pt[i] = mBreastParamsUser[i]->getWeight();
+		}
+	}
+	
+	LLVector3 breast_current_local_pt = mBreastLastPosition_local_pt;
+
+	//
+	// End parameters and settings
+	////////////////////////////////////////////////////////////////////////////////
+
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Calculate velocity and acceleration in parameter space.
+	//
+
+	const LLVector3 char_velocity_local_vec = calculateVelocity_local(time_delta);
+	const LLVector3 char_acceleration_local_vec = calculateAcceleration_local(char_velocity_local_vec, time_delta);
+	mCharLastVelocity_local_vec = char_velocity_local_vec;
+
+	LLJoint *chest_joint = mChestState->getJoint();
+	mCharLastPosition_world_pt = chest_joint->getWorldPosition();
+
+	//
+	// End velocity and acceleration
+	////////////////////////////////////////////////////////////////////////////////
+
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Calculate the total force 
+	//
+
+	// Spring force is a restoring force towards the original user-set breast position.
+	// F = kx
+	const LLVector3 spring_length_local = breast_current_local_pt-breast_user_local_pt;
+	LLVector3 force_spring_local_vec = -spring_length_local; force_spring_local_vec *= mBreastSpringParam;
+
+	// Acceleration is the force that comes from the change in velocity of the torso.
+	// F = ma + mg
+	LLVector3 force_accel_local_vec = char_acceleration_local_vec * mBreastMassParam;
+	const LLVector3 force_gravity_local_vec = toLocal(LLVector3(0,0,1))* mBreastGravityParam * mBreastMassParam;
+	force_accel_local_vec += force_gravity_local_vec;
+	force_accel_local_vec *= mBreastGainParam;
+
+	// Damping is a restoring force that opposes the current velocity.
+	// F = -kv
+	LLVector3 force_damping_local_vec = -mBreastDampingParam; 
+	force_damping_local_vec *= mBreastVelocity_local_vec;
+	
+	// Drag is a force imparted by velocity, intuitively it is similar to wind resistance.
+	// F = .5v*v
+	LLVector3 force_drag_local_vec = .5*char_velocity_local_vec;
+	force_drag_local_vec *= char_velocity_local_vec;
+	force_drag_local_vec *= mBreastDragParam[0];
+
+	LLVector3 force_net_local_vec = 
+		force_accel_local_vec + 
+		force_gravity_local_vec +
+		force_spring_local_vec + 
+		force_damping_local_vec + 
+		force_drag_local_vec;
+
+	//
+	// End total force
+	////////////////////////////////////////////////////////////////////////////////
+
+	
+	////////////////////////////////////////////////////////////////////////////////
+	// Calculate new params
+	//
+
+	// Calculate the new acceleration based on the net force.
+	// a = F/m
+	LLVector3 acceleration_local_vec = force_net_local_vec / mBreastMassParam;
+	mBreastVelocity_local_vec += acceleration_local_vec;
+	mBreastVelocity_local_vec.clamp(-mBreastMaxVelocityParam*100.0, mBreastMaxVelocityParam*100.0);
+
+	// Temporary debugging setting to cause all avatars to move, for profiling purposes.
+	if (gSavedSettings.getBOOL("AvatarPhysicsTest"))
+	{
+		mBreastVelocity_local_vec[0] = sin(mTimer.getElapsedTimeF32()*4.0)*5.0;
+		mBreastVelocity_local_vec[1] = sin(mTimer.getElapsedTimeF32()*3.0)*5.0;
+	}
+	// Calculate the new parameters and clamp them to the min/max ranges.
+	LLVector3 new_local_pt = breast_current_local_pt + mBreastVelocity_local_vec*time_delta;
+	new_local_pt.clamp(mBreastParamsMin,mBreastParamsMax);
+		
+	// Set the new parameters.
+	for (U32 i=0; i < 3; i++)
+	{
+		// If the param is disabled, just set the param to the user value.
+		if (mBreastMaxVelocityParam[i] == 0)
+		{
+			new_local_pt[i] = breast_user_local_pt[i];
+		}
+		if (mBreastParamsDriven[i])
+		{
+			mCharacter->setVisualParamWeight(mBreastParamsDriven[i],
+											 new_local_pt[i],
+											 FALSE);
+		}
+	}
+
+	mBreastLastPosition_local_pt = new_local_pt;
+	
+	//
+	// 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 BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(this) != NULL);
+	if (!is_self)
+	{
+		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());
+		if (pixel_area < area_for_this_setting)
+		{
+			return TRUE;
+		}
+	}
+
+	// If the parameter hasn't changed enough, then don't update.
+	LLVector3 position_diff = mBreastLastUpdatePosition_local_pt-new_local_pt;
+	for (U32 i=0; i < 3; i++)
+	{
+		const F32 min_delta = (1.0-lod_factor)*(mBreastParamsMax[i]-mBreastParamsMin[i])/2.0;
+		if (llabs(position_diff[i]) > min_delta)
+		{
+			mCharacter->updateVisualParams();
+			mBreastLastUpdatePosition_local_pt = new_local_pt;
+			return TRUE;
+		}
+	}
+	
+	//
+	// End update visual params
+	////////////////////////////////////////////////////////////////////////////////
+
+	return TRUE;
+}
diff --git a/indra/newview/llbreastmotion.h b/indra/newview/llbreastmotion.h
new file mode 100644
index 0000000000000000000000000000000000000000..8578d4ad1ac9f93fe0147d56c2d4f8aa98fb7466
--- /dev/null
+++ b/indra/newview/llbreastmotion.h
@@ -0,0 +1,160 @@
+/** 
+ * @file llbreastmotion.h
+ * @brief Implementation of LLBreastMotion 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_LLBREASTMOTION_H
+#define LL_LLBREASTMOTION_H
+
+//-----------------------------------------------------------------------------
+// Header files
+//-----------------------------------------------------------------------------
+#include "llmotion.h"
+#include "llframetimer.h"
+
+#define BREAST_MOTION_FADEIN_TIME 1.0f
+#define BREAST_MOTION_FADEOUT_TIME 1.0f
+
+class LLViewerVisualParam;
+
+//-----------------------------------------------------------------------------
+// class LLBreastMotion
+//-----------------------------------------------------------------------------
+class LLBreastMotion :
+	public LLMotion
+{
+public:
+	// Constructor
+	LLBreastMotion(const LLUUID &id);
+
+	// Destructor
+	virtual ~LLBreastMotion();
+
+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 LLBreastMotion(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 BREAST_MOTION_FADEIN_TIME; }
+
+	// motions must report their "ease out" duration.
+	virtual F32 getEaseOutDuration() { return BREAST_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();
+
+protected:
+	LLVector3 toLocal(const LLVector3 &world_vector);
+	LLVector3 calculateVelocity_local(const F32 time_delta);
+	LLVector3 calculateAcceleration_local(const LLVector3 &new_char_velocity_local_vec,
+										  const F32 time_delta);
+	F32 calculateTimeDelta();
+private:
+	//-------------------------------------------------------------------------
+	// joint states to be animated
+	//-------------------------------------------------------------------------
+	LLPointer<LLJointState> mChestState;
+	LLCharacter*		mCharacter;
+
+
+	//-------------------------------------------------------------------------
+	// miscellaneous parameters
+	//-------------------------------------------------------------------------
+	LLViewerVisualParam *mBreastParamsUser[3];
+	LLViewerVisualParam *mBreastParamsDriven[3];
+	LLVector3           mBreastParamsMin;
+	LLVector3           mBreastParamsMax;
+
+	LLVector3           mCharLastPosition_world_pt; // Last position of the avatar
+	LLVector3			mCharLastVelocity_local_vec; // How fast the character is moving
+	LLVector3           mCharLastAcceleration_local_vec; // Change in character velocity
+
+	LLVector3           mBreastLastPosition_local_pt; // Last parameters for breast
+	LLVector3           mBreastVelocity_local_vec; // How fast the breast params are moving
+	LLVector3           mBreastLastUpdatePosition_local_pt; // Last parameters when visual update was sent
+
+
+	F32 mBreastMassParam;
+	F32 mBreastGravityParam;
+	U32 mBreastSmoothingParam;
+
+	LLVector3 mBreastSpringParam;
+	LLVector3 mBreastDampingParam;
+	LLVector3 mBreastGainParam;
+	LLVector3 mBreastMaxVelocityParam;
+	LLVector3 mBreastDragParam;
+
+	LLFrameTimer	mTimer;
+	F32             mLastTime;
+	
+	U32            mFileTicks;
+};
+
+#endif // LL_LLBREASTMOTION_H
+
diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h
index a0e45cf5e5654091cd282f06969a712863e2fec1..fb1b44458ce76a4eedf162517f278a646abccd17 100644
--- a/indra/newview/lldriverparam.h
+++ b/indra/newview/lldriverparam.h
@@ -30,6 +30,7 @@
 #include "llviewervisualparam.h"
 #include "llwearabletype.h"
 
+class LLPhysicsMotion;
 class LLVOAvatar;
 class LLWearable;
 
@@ -76,6 +77,7 @@ protected:
 
 class LLDriverParam : public LLViewerVisualParam
 {
+	friend class LLPhysicsMotion; // physics motion needs to access driven params directly.
 public:
 	LLDriverParam(LLVOAvatar *avatarp);
 	LLDriverParam(LLWearable *wearablep);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 724096b443a11c2ee7927733b5ec4839c6608707..ffbb0efad3916bc25a5f668d0577969c8013ec35 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1200,6 +1200,7 @@ void LLFloaterPreference::refresh()
 	updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail",	true), getChild<LLTextBox>("FlexibleMeshDetailText",	true));
 	updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail",		true), getChild<LLTextBox>("TreeMeshDetailText",		true));
 	updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail",		true), getChild<LLTextBox>("AvatarMeshDetailText",		true));
+	updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail",	true), getChild<LLTextBox>("AvatarPhysicsDetailText",		true));
 	updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail",	true), getChild<LLTextBox>("TerrainMeshDetailText",		true));
 	updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess",	true), getChild<LLTextBox>("PostProcessText",			true));
 	updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail",		true), getChild<LLTextBox>("SkyMeshDetailText",			true));
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 4c2e0fa709993ef1c8695ec913f1812d59ac0f8a..622a5607df055f7cfa7c3b8807a81e6dc51a4540 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4674,10 +4674,18 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 					else
 					{
 						items.push_back(std::string("Wearable And Object Wear"));
-						items.push_back(std::string("Wearable Add"));
 						disabled_items.push_back(std::string("Take Off"));
 						disabled_items.push_back(std::string("Wearable Edit"));
 					}
+
+					if (LLWearableType::getAllowMultiwear(mWearableType))
+					{
+						items.push_back(std::string("Wearable Add"));
+						if (gAgentWearables.getWearableCount(mWearableType) > 0)
+						{
+							disabled_items.push_back(std::string("Wearable Add"));
+						}
+					}
 					break;
 				default:
 					break;
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 3f4f33e88db9267a7becde099a9b5353c24b70c2..95dea219a8e9c52e6eb093880100a8389564b01a 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -82,6 +82,8 @@ LLIconDictionary::LLIconDictionary()
 	addEntry(LLInventoryIcon::ICONNAME_ANIMATION, 				new IconEntry("Inv_Animation"));
 	addEntry(LLInventoryIcon::ICONNAME_GESTURE, 				new IconEntry("Inv_Gesture"));
 
+	addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, 		new IconEntry("Inv_Physics"));
+
 	addEntry(LLInventoryIcon::ICONNAME_LINKITEM, 				new IconEntry("Inv_LinkItem"));
 	addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, 				new IconEntry("Inv_LinkFolder"));
 
diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h
index 9a2cc080955577616c3c7f8b30f191a894a43e8c..694b56d57275d83308e6a1d521ad0abb287a3c86 100644
--- a/indra/newview/llinventoryicon.h
+++ b/indra/newview/llinventoryicon.h
@@ -66,9 +66,11 @@ public:
 		ICONNAME_CLOTHING_SKIRT,
 		ICONNAME_CLOTHING_ALPHA,
 		ICONNAME_CLOTHING_TATTOO,
-		
+
 		ICONNAME_ANIMATION,
 		ICONNAME_GESTURE,
+
+		ICONNAME_CLOTHING_PHYSICS,
 		
 		ICONNAME_LINKITEM,
 		ICONNAME_LINKFOLDER,
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 4a74b7925c1965afd7313369e74301d356d52df3..4db9a154ea63a60827927ce5a7fcb5d7cdaaf120 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -94,7 +94,13 @@ enum ESubpart {
 	SUBPART_UNDERPANTS,
 	SUBPART_SKIRT,
 	SUBPART_ALPHA,
-	SUBPART_TATTOO
+	SUBPART_TATTOO,
+	SUBPART_PHYSICS_BREASTS_UPDOWN,
+	SUBPART_PHYSICS_BREASTS_INOUT,
+	SUBPART_PHYSICS_BELLY_UPDOWN,
+	SUBPART_PHYSICS_BUTT_UPDOWN,
+	SUBPART_PHYSICS_BUTT_LEFTRIGHT,
+	SUBPART_PHYSICS_ADVANCED,
  };
 
 using namespace LLVOAvatarDefines;
@@ -218,7 +224,7 @@ LLEditWearableDictionary::Wearables::Wearables()
 	// note the subpart that is listed first is treated as "default", regardless of what order is in enum.
 	// Please match the order presented in XUI. -Nyx
 	// this will affect what camera angle is shown when first editing a wearable
-	addEntry(LLWearableType::WT_SHAPE, 		new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9,	SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS ));
+	addEntry(LLWearableType::WT_SHAPE, 		new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9,	SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS));
 	addEntry(LLWearableType::WT_SKIN, 		new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text",0,3,4, TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
 	addEntry(LLWearableType::WT_HAIR, 		new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text",0,1,4, TEX_HAIR, SUBPART_HAIR_COLOR,	SUBPART_HAIR_STYLE,	SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
 	addEntry(LLWearableType::WT_EYES, 		new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text",0,1,1, TEX_EYES_IRIS, SUBPART_EYES));
@@ -233,6 +239,7 @@ LLEditWearableDictionary::Wearables::Wearables()
 	addEntry(LLWearableType::WT_SKIRT, 		new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT));
 	addEntry(LLWearableType::WT_ALPHA, 		new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA));
 	addEntry(LLWearableType::WT_TATTOO, 	new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1,3,1, TEX_HEAD_TATTOO, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO));
+	addEntry(LLWearableType::WT_PHYSICS, 	new WearableEntry(LLWearableType::WT_PHYSICS,"edit_physics_title","physics_desc_text",0,0,6, SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED));
 }
 
 LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type,
@@ -303,6 +310,12 @@ LLEditWearableDictionary::Subparts::Subparts()
 	addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
 	addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
 	addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
+	addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
+	addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
+	addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+	addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+	addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+	addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
 }
 
 LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
@@ -740,6 +753,7 @@ BOOL LLPanelEditWearable::postBuild()
 	mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
 	mPanelAlpha = getChild<LLPanel>("edit_alpha_panel");
 	mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel");
+	mPanelPhysics = getChild<LLPanel>("edit_physics_panel");
 
 	mTxtAvatarHeight = mPanelShape->getChild<LLTextBox>("avatar_height");
 
@@ -848,11 +862,11 @@ void LLPanelEditWearable::setVisible(BOOL visible)
 	LLPanel::setVisible(visible);
 }
 
-void LLPanelEditWearable::setWearable(LLWearable *wearable)
+void LLPanelEditWearable::setWearable(LLWearable *wearable, BOOL disable_camera_switch)
 {
-	showWearable(mWearablePtr, FALSE);
+	showWearable(mWearablePtr, FALSE, disable_camera_switch);
 	mWearablePtr = wearable;
-	showWearable(mWearablePtr, TRUE);
+	showWearable(mWearablePtr, TRUE, disable_camera_switch);
 }
 
 
@@ -1052,7 +1066,7 @@ void LLPanelEditWearable::revertChanges()
 	gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE);
 }
 
-void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
+void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch)
 {
 	if (!wearable)
 	{
@@ -1147,7 +1161,10 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
 	
 			updateScrollingPanelUI();
 		}
-		showDefaultSubpart();
+		if (!disable_camera_switch)
+		{
+			showDefaultSubpart();
+		}
 
 		updateVerbs();
 	}
@@ -1155,7 +1172,7 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
 
 void LLPanelEditWearable::showDefaultSubpart()
 {
-	changeCamera(0);
+	changeCamera(3);
 }
 
 void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index)
@@ -1356,6 +1373,11 @@ LLPanel* LLPanelEditWearable::getPanel(LLWearableType::EType type)
 		case LLWearableType::WT_TATTOO:
 			return mPanelTattoo;
 			break;
+
+		case LLWearableType::WT_PHYSICS:
+			return mPanelPhysics;
+			break;
+
 		default:
 			break;
 	}
@@ -1403,7 +1425,16 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value
 		{
 			LLPanel::Params p;
 			p.name("LLScrollingPanelParam");
-			LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+			LLWearable *wearable = this->getWearable();
+			LLScrollingPanelParamBase *panel_param = NULL;
+			if (wearable && wearable->getType() == LLWearableType::WT_PHYSICS) // Hack to show a different panel for physics.  Should generalize this later.
+			{
+				panel_param = new LLScrollingPanelParamBase( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+			}
+			else
+			{
+				panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+			}
 			height = panel_list->addPanel( panel_param );
 		}
 	}
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
index 43513d8ab3fb4d61585d04f28bae7c06e9ff3e04..692a7ce90fa06df8939da6d094ca1acbb3ec9614 100644
--- a/indra/newview/llpaneleditwearable.h
+++ b/indra/newview/llpaneleditwearable.h
@@ -55,8 +55,11 @@ public:
 	/*virtual*/ BOOL		isDirty() const;	// LLUICtrl
 	/*virtual*/ void		draw();	
 
+	// changes camera angle to default for selected subpart
+	void				changeCamera(U8 subpart);
+
 	LLWearable* 		getWearable() { return mWearablePtr; }
-	void				setWearable(LLWearable *wearable);
+	void				setWearable(LLWearable *wearable, BOOL disable_camera_switch = FALSE);
 
 	void				saveChanges(bool force_save_as = false);
 	void				revertChanges();
@@ -77,7 +80,7 @@ public:
 private:
 	typedef std::map<F32, LLViewerVisualParam*> value_map_t;
 
-	void				showWearable(LLWearable* wearable, BOOL show);
+	void				showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE);
 	void				updateScrollingPanelUI();
 	LLPanel*			getPanel(LLWearableType::EType type);
 	void				getSortedParams(value_map_t &sorted_params, const std::string &edit_group);
@@ -91,9 +94,6 @@ private:
 	void				toggleTypeSpecificControls(LLWearableType::EType type);
 	void				updateTypeSpecificControls(LLWearableType::EType type);
 
-	// changes camera angle to default for selected subpart
-	void				changeCamera(U8 subpart);
-
 	//alpha mask checkboxes
 	void configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name);
 	void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te);
@@ -163,6 +163,7 @@ private:
 	LLPanel *mPanelSkirt;
 	LLPanel *mPanelAlpha;
 	LLPanel *mPanelTattoo;
+	LLPanel *mPanelPhysics;
 
 	typedef std::map<std::string, LLVOAvatarDefines::ETextureIndex> string_texture_index_map_t;
 	string_texture_index_map_t mAlphaCheckbox2Index;
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 9346e48d1ecbc53f416125fd82ee95612eacca42..62f582c34366c9e4a92fca6aa8e196ba922c285e 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -466,6 +466,7 @@ BOOL LLPanelOutfitEdit::postBuild()
 	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT)));
 	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA)));
 	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO)));
+	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("physics"), new LLFindActualWearablesOfType(LLWearableType::WT_PHYSICS)));
 
 	mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name"); 
 	mStatus = getChild<LLTextBox>("status");
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index fd366e9cbce518e6e029305d7adc46a26ac82255..5d4b8d46444e773a30a913934b5874f6dbae304b 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -97,6 +97,7 @@ public:
 		LVIT_SKIRT,
 		LVIT_ALPHA,
 		LVIT_TATTOO,
+		LVIT_PHYSICS,
 		NUM_LIST_VIEW_ITEM_TYPES
 	} EListViewItemType; 
 
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73de1cef3f432c9397e84d60d09c64ebd7eb457f
--- /dev/null
+++ b/indra/newview/llphysicsmotion.cpp
@@ -0,0 +1,698 @@
+/** 
+ * @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 "llcharacter.h"
+#include "llviewercontrol.h"
+#include "llviewervisualparam.h"
+#include "llvoavatarself.h"
+
+typedef std::map<std::string, std::string> controller_map_t;
+typedef std::map<std::string, F32> default_controller_map_t;
+
+#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
+
+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_user_name: The param (if any) that the user sees and controls.  This is what
+	  the particular property would look like without physics.  For example, it may be
+	  the breast gravity.  This param's value should will not be altered, and is only
+	  used as a reference point for the rest position of the body party.  This is usually
+	  a driver param and the param(s) that physics is altering are the driven params.
+
+	  param_driven_name: The param whose value is actually set by the physics.  If you
+	  leave this blank (which should suffice normally), the physics will assume that
+	  param_user_name is a driver param and will set the params that the driver is
+	  in charge of (i.e. the "driven" params).
+
+	  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 &param_user_name, 
+			const std::string &param_driven_name,
+			const std::string &joint_name,
+			LLCharacter *character,
+			const LLVector3 &motion_direction_vec,
+			const controller_map_t &controllers) :
+		mParamUserName(param_user_name),
+		mParamDrivenName(param_driven_name),
+		mJointName(joint_name),
+		mMotionDirectionVec(motion_direction_vec),
+		mParamUser(NULL),
+		mParamDriven(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);
+
+	LLPointer<LLJointState> 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 toLocal(const LLVector3 &world);
+	F32 calculateVelocity_local(const F32 time_delta);
+	F32 calculateAcceleration_local(F32 velocity_local,
+					const F32 time_delta);
+private:
+	const std::string mParamDrivenName;
+	const std::string mParamUserName;
+	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 *mParamUser;
+	LLViewerVisualParam *mParamDriven;
+	const controller_map_t mParamControllers;
+	
+	LLPointer<LLJointState> 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["Smoothing"] = 2.0f;
+	controller["Gravity"] = 0.0f;
+	controller["Damping"] = .05f;
+	controller["Drag"] = 0.15f;
+	controller["MaxSpeed"] = 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);
+
+	mParamUser = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamUserName.c_str());
+	if (mParamDrivenName != "")
+		mParamDriven = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamDrivenName.c_str());
+	if (mParamUser == NULL)
+	{
+		llinfos << "Failure reading in  [ " << mParamUserName << " ]" << 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["Smoothing"] = "Breast_Physics_Smoothing";
+		controller["Gravity"] = "Breast_Physics_Gravity";
+		controller["Damping"] = "Breast_Physics_InOut_Damping";
+		controller["Drag"] = "Breast_Physics_InOut_Drag";
+		controller["MaxSpeed"] = "Breast_Physics_InOut_Max_Velocity";
+		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["Smoothing"] = "Breast_Physics_Smoothing";
+		controller["Gravity"] = "Breast_Physics_Gravity";
+		controller["Damping"] = "Breast_Physics_UpDown_Damping";
+		controller["Drag"] = "Breast_Physics_UpDown_Drag";
+		controller["MaxSpeed"] = "Breast_Physics_UpDown_Max_Velocity";
+		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);
+	}
+	
+	// Butt Bounce
+	{
+		controller_map_t controller;
+		controller["Mass"] = "Butt_Physics_Mass";
+		controller["Smoothing"] = "Butt_Physics_Smoothing";
+		controller["Gravity"] = "Butt_Physics_Gravity";
+		controller["Damping"] = "Butt_Physics_UpDown_Damping";
+		controller["Drag"] = "Butt_Physics_UpDown_Drag";
+		controller["MaxSpeed"] = "Butt_Physics_UpDown_Max_Velocity";
+		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["Smoothing"] = "Butt_Physics_Smoothing";
+		controller["Gravity"] = "Butt_Physics_Gravity";
+		controller["Damping"] = "Butt_Physics_LeftRight_Damping";
+		controller["Drag"] = "Butt_Physics_LeftRight_Drag";
+		controller["MaxSpeed"] = "Butt_Physics_LeftRight_Max_Velocity";
+		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["Smoothing"] = "Belly_Physics_Smoothing";
+		controller["Gravity"] = "Belly_Physics_Gravity";
+		controller["Damping"] = "Belly_Physics_UpDown_Damping";
+		controller["Drag"] = "Belly_Physics_UpDown_Drag";
+		controller["MaxSpeed"] = "Belly_Physics_UpDown_Max_Velocity";
+		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_BREAST_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 time_delta)
+{
+	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 velocity_world = (position_world-last_position_world) / time_delta;
+	const F32 velocity_local = toLocal(velocity_world);
+	return velocity_local;
+}
+
+F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local,
+						 const F32 time_delta)
+{
+	const F32 smoothing = getParamValue("Smoothing");
+	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;
+	for (motion_vec_t::iterator iter = mMotions.begin();
+	     iter != mMotions.end();
+	     ++iter)
+	{
+		LLPhysicsMotion *motion = (*iter);
+		update_visuals |= motion->onUpdate(time);
+	}
+		
+	if (update_visuals)
+		mCharacter->updateVisualParams();
+	
+	return TRUE;
+}
+
+
+// Return TRUE if character has to update visual params.
+BOOL LLPhysicsMotion::onUpdate(F32 time)
+{
+	// static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w");
+	
+	if (!mParamUser)
+		return FALSE;
+
+	if (!mLastTime)
+	{
+		mLastTime = time;
+		return FALSE;
+	}
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Get all parameters and settings
+	//
+
+	const F32 time_delta = time - mLastTime;
+	if (time_delta > 3.0 || time_delta <= 0.01)
+	{
+		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 = gSavedSettings.getBOOL("AvatarPhysicsTest");
+	
+	F32 behavior_maxspeed = getParamValue("MaxSpeed");
+	if (physics_test)
+		behavior_maxspeed = 100.0f;
+
+	if (behavior_maxspeed == 0)
+		return FALSE;
+
+	F32 position_current_local = llclamp(mPosition_local,
+					     0.0f,
+					     1.0f); // Normalized [0,1] range
+
+	// 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.
+	F32 position_user_local = mParamUser->getWeight();
+	position_user_local = (position_user_local - mParamUser->getMinWeight()) / (mParamUser->getMaxWeight() - mParamUser->getMinWeight());
+
+	//
+	// End parameters and settings
+	////////////////////////////////////////////////////////////////////////////////
+
+
+	////////////////////////////////////////////////////////////////////////////////
+	// Calculate velocity and acceleration in parameter space.
+	//
+	
+	const F32 velocity_joint_local = calculateVelocity_local(time_delta);
+	const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local, time_delta);
+
+	//
+	// End velocity and acceleration
+	////////////////////////////////////////////////////////////////////////////////
+
+
+	////////////////////////////////////////////////////////////////////////////////
+	// 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 = behavior_gain * (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;
+	F32 velocity_new_local = mVelocity_local + acceleration_new_local;
+	velocity_new_local = llclamp(velocity_new_local, 
+				     -behavior_maxspeed, behavior_maxspeed);
+	
+	// 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.
+	const F32 position_new_local = (behavior_maxspeed != 0) ? 
+		(position_current_local + velocity_new_local*time_delta) :
+		position_user_local;
+
+	// Zero out the velocity if the param is being pushed beyond its limits.
+	if (position_new_local < 0 || position_new_local > 1)
+	{
+		velocity_new_local = 0;
+	}
+
+	const F32 position_new_local_clamped = llclamp(position_new_local,
+						       0.0f,
+						       1.0f);
+
+	// Set the new param.
+	// If a specific param has been declared, then set that one.
+	// Otherwise, assume that the param is a driver param, and
+	// set the params that it drives.
+	if (mParamDriven)
+	{
+		setParamValue(mParamDriven,position_new_local_clamped);
+	}
+	else
+	{
+		LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamUser);
+		llassert_always(driver_param);
+		if (driver_param)
+		{
+			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);
+			}
+		}
+	}
+	
+	//
+	// 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.
+	
+	BOOL update_visuals = FALSE;
+
+	// 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<LLVOAvatarSelf *>(mCharacter) != NULL);
+	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.01f-lod_factor)*0.4f;
+		if (llabs(position_diff_local) > min_delta)
+		{
+			update_visuals = TRUE;
+			mPositionLastUpdate_local = position_new_local;
+		}
+	}
+
+	//
+	// End update visual params
+	////////////////////////////////////////////////////////////////////////////////
+
+	mVelocityJoint_local = velocity_joint_local;
+
+	mVelocity_local = velocity_new_local;
+	mAccelerationJoint_local = acceleration_joint_local;
+	mPosition_local = position_new_local;
+
+	mPosition_world = joint->getWorldPosition();
+	mLastTime = time;
+
+	/*
+	  // 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)
+{
+	const F32 value_min_local = param->getMinWeight();
+	const F32 value_max_local = param->getMaxWeight();
+
+	const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_normalized;
+
+	mCharacter->setVisualParamWeight(param,
+					 new_value_local,
+					 FALSE);
+}
diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c0087d269119589b60ddad4e8731bfb193a760a
--- /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<LLPhysicsMotion *> motion_vec_t;
+	motion_vec_t mMotions;
+};
+
+#endif // LL_LLPHYSICSMOTION_H
+
diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index 363b0b8e9d18185969120fc4d24f7e091a9a70d6..6d6fb2fa0ef8cfff3d5a1a35b8767c5e085df97b 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -46,6 +46,10 @@
 
 extern LLControlGroup gSavedSettings;				// read only
 
+LLPolyMorphData *clone_morph_param(const LLPolyMorphData *src_data,
+				   const LLVector3 &direction,
+				   const std::string &name);
+
 //-----------------------------------------------------------------------------
 // Global table of loaded LLPolyMeshes
 //-----------------------------------------------------------------------------
@@ -602,6 +606,40 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName )
 				}
 
 				mMorphData.insert(morph_data);
+
+				if (!strcmp(morphName, "Big_Belly_Torso"))
+				{
+					mMorphData.insert(clone_morph_param(morph_data,
+									    LLVector3(0,0,0.03f),
+									    "Belly_Physics_Torso_UpDown_Driven"));
+				}
+
+				if (!strcmp(morphName, "Big_Belly_Legs"))
+				{
+					mMorphData.insert(clone_morph_param(morph_data,
+									    LLVector3(0,0,0.03f),
+									    "Belly_Physics_Legs_UpDown_Driven"));
+				}
+
+				if (!strcmp(morphName, "skirt_belly"))
+				{
+					mMorphData.insert(clone_morph_param(morph_data,
+									    LLVector3(0,0,0.03f),
+									    "Belly_Physics_Skirt_UpDown_Driven"));
+				}
+
+				if (!strcmp(morphName, "Small_Butt"))
+				{
+					mMorphData.insert(clone_morph_param(morph_data,
+									    LLVector3(0,0,0.015f),
+									    "Butt_Physics_UpDown_Driven"));
+				}
+				if (!strcmp(morphName, "Small_Butt"))
+				{
+					mMorphData.insert(clone_morph_param(morph_data,
+									    LLVector3(0,0.015f,0),
+									    "Butt_Physics_LeftRight_Driven"));
+				}
 			}
 
 			S32 numRemaps;
@@ -1158,4 +1196,20 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
 	mLastWeight = mCurWeight;
 }
 
+
+LLPolyMorphData *clone_morph_param(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;
+}
+
 // End
diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp
index 0ffe1c635f143a5780be304fbb4c7ffa3c4c055b..5a67fd482a7294319ec83a6ae95d32a9e5f5c357 100644
--- a/indra/newview/llpolymorph.cpp
+++ b/indra/newview/llpolymorph.cpp
@@ -59,6 +59,37 @@ 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()
 //-----------------------------------------------------------------------------
@@ -287,10 +318,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)
+	{
+		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 " << getInfo()->mMorphName << " found in mesh." << llendl;
+		llwarns << "No morph target named " << morph_param_name << " found in mesh." << llendl;
 		return FALSE;  // Continue, ignoring this tag
 	}
 	return TRUE;
diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h
index bc111882b709d8a67593f0d8dd5074662a95d2ba..8a024f2e9e05c55b83bb987f0f36a2d98ff3d86a 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/newview/llpolymorph.h
@@ -46,6 +46,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/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
index f8c20dada07429cef4a4b1e5689558b31efd2442..05b82ba967e3dfda182491e45553b80da7d32c42 100644
--- a/indra/newview/llscrollingpanelparam.cpp
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -50,14 +50,9 @@ const S32 LLScrollingPanelParam::PARAM_HINT_HEIGHT = 128;
 S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
 
 LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
-											  LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp )
-	: LLScrollingPanel( panel_params ),
-	  mParam(param),
-	  mAllowModify(allow_modify),
-	  mWearable(wearable)
+					      LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints )
+    : LLScrollingPanelParamBase( panel_params, mesh, param, allow_modify, wearable, jointp, use_hints)
 {
-	buildFromFile( "panel_scrolling_param.xml");
-
 	// *HACK To avoid hard coding texture position, lets use border's position for texture. 
 	LLViewBorder* left_border = getChild<LLViewBorder>("left_border");
 
@@ -73,12 +68,6 @@ LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_param
 	
 	mHintMin->setAllowsUpdates( FALSE );
 	mHintMax->setAllowsUpdates( FALSE );
-	getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));
-
-	std::string display_name = LLTrans::getString(param->getDisplayName());
-	getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
-	getChildView("param slider")->setEnabled(mAllowModify);
-	childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);
 
 	std::string min_name = LLTrans::getString(param->getMinDisplayName());
 	std::string max_name = LLTrans::getString(param->getMaxDisplayName());
@@ -112,20 +101,15 @@ LLScrollingPanelParam::~LLScrollingPanelParam()
 }
 void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
 {
-	LLViewerVisualParam* param = mHintMin->getVisualParam();
-
 	if (!mWearable)
 	{
 		// not editing a wearable just now, no update necessary
 		return;
 	}
-	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
-	getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
+	LLScrollingPanelParamBase::updatePanel(allow_modify);
+
 	mHintMin->requestUpdate( sUpdateDelayFrames++ );
 	mHintMax->requestUpdate( sUpdateDelayFrames++ );
-
-	mAllowModify = allow_modify;
-	getChildView("param slider")->setEnabled(mAllowModify);
 	getChildView("less")->setEnabled(mAllowModify);
 	getChildView("more")->setEnabled(mAllowModify);
 }
@@ -135,13 +119,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++ );
 		}
 	}
 }
@@ -164,7 +152,7 @@ void LLScrollingPanelParam::draw()
 	getChildView("min param text")->setVisible( FALSE );
 	getChildView("max param text")->setVisible( FALSE );
 	LLPanel::draw();
-
+	
 	// If we're in a focused floater, don't apply the floater's alpha to visual param hint,
 	// making its behavior similar to texture controls'.
 	F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
@@ -195,23 +183,6 @@ void LLScrollingPanelParam::draw()
 	drawChild(getChild<LLView>("max param text"));
 }
 
-// static
-void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
-{
-	LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
-	LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
-	LLViewerVisualParam* param = self->mParam;
-	
-	F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
-	F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
-	if (current_weight != new_weight )
-	{
-		self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
-		self->mWearable->writeToAvatar();
-		gAgentAvatarp->updateVisualParams();
-	}
-}
-
 // static
 void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
 {
@@ -221,7 +192,6 @@ void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
 void LLScrollingPanelParam::onSliderMouseUp(LLUICtrl* ctrl, void* userdata)
 {
 	LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
-
 	LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
 }
 
diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h
index 1cbc64f45a9c6ec468fe77eff83c1dd68d29ae7b..c7a47d5c7a585fe924de09d0ea07ed269d99ac01 100644
--- a/indra/newview/llscrollingpanelparam.h
+++ b/indra/newview/llscrollingpanelparam.h
@@ -28,8 +28,7 @@
 #ifndef LL_SCROLLINGPANELPARAM_H
 #define LL_SCROLLINGPANELPARAM_H
 
-#include "llpanel.h"
-#include "llscrollingpanellist.h"
+#include "llscrollingpanelparambase.h"
 
 class LLViewerJointMesh;
 class LLViewerVisualParam;
@@ -38,11 +37,11 @@ class LLVisualParamHint;
 class LLViewerVisualParam;
 class LLJoint;
 
-class LLScrollingPanelParam : public LLScrollingPanel
+class LLScrollingPanelParam : public LLScrollingPanelParamBase
 {
 public:
 	LLScrollingPanelParam( const LLPanel::Params& panel_params,
-						   LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp );
+			       LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints = TRUE );
 	virtual ~LLScrollingPanelParam();
 
 	virtual void		draw();
@@ -50,7 +49,6 @@ public:
 	virtual void		updatePanel(BOOL allow_modify);
 
 	static void			onSliderMouseDown(LLUICtrl* ctrl, void* userdata);
-	static void			onSliderMoved(LLUICtrl* ctrl, void* userdata);
 	static void			onSliderMouseUp(LLUICtrl* ctrl, void* userdata);
 
 	static void			onHintMinMouseDown(void* userdata);
@@ -74,7 +72,6 @@ public:
 	const static S32 PARAM_HINT_HEIGHT;
 
 public:
-	LLViewerVisualParam* mParam;
 	LLPointer<LLVisualParamHint>	mHintMin;
 	LLPointer<LLVisualParamHint>	mHintMax;
 	static S32 			sUpdateDelayFrames;
@@ -82,9 +79,7 @@ public:
 protected:
 	LLTimer				mMouseDownTimer;	// timer for how long mouse has been held down on a hint.
 	F32					mLastHeldTime;
-
 	BOOL mAllowModify;
-	LLWearable *mWearable;
 }; 
 
 #endif
diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..62e3039d2fe67ea1f2183395b18bfbd17ae13af3
--- /dev/null
+++ b/indra/newview/llscrollingpanelparambase.cpp
@@ -0,0 +1,112 @@
+/** 
+ * @file llscrollingpanelparam.cpp
+ * @brief UI panel for a list of visual param panels
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llscrollingpanelparambase.h"
+#include "llviewerjointmesh.h"
+#include "llviewervisualparam.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
+#include "lltoolmorph.h"
+#include "lltrans.h"
+#include "llbutton.h"
+#include "llsliderctrl.h"
+#include "llagent.h"
+#include "llviewborder.h"
+#include "llvoavatarself.h"
+
+LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& panel_params,
+						      LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints)
+	: LLScrollingPanel( panel_params ),
+	  mParam(param),
+	  mAllowModify(allow_modify),
+	  mWearable(wearable)
+{
+	if (use_hints)
+		buildFromFile( "panel_scrolling_param.xml");
+	else
+		buildFromFile( "panel_scrolling_param_base.xml");
+	
+	getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));
+
+	std::string display_name = LLTrans::getString(param->getDisplayName());
+	getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
+	getChildView("param slider")->setEnabled(mAllowModify);
+	childSetCommitCallback("param slider", LLScrollingPanelParamBase::onSliderMoved, this);
+
+	setVisible(FALSE);
+	setBorderVisible( FALSE );
+}
+
+LLScrollingPanelParamBase::~LLScrollingPanelParamBase()
+{
+}
+
+void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify)
+{
+	LLViewerVisualParam* param = mParam;
+
+	if (!mWearable)
+	{
+		// not editing a wearable just now, no update necessary
+		return;
+	}
+
+	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
+	getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
+	mAllowModify = allow_modify;
+	getChildView("param slider")->setEnabled(mAllowModify);
+}
+
+// static
+void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
+{
+	LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
+	LLScrollingPanelParamBase* self = (LLScrollingPanelParamBase*) userdata;
+	LLViewerVisualParam* param = self->mParam;
+	
+	F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
+	F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
+	if (current_weight != new_weight )
+	{
+		self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
+		self->mWearable->writeToAvatar();
+		gAgentAvatarp->updateVisualParams();
+	}
+}
+
+F32 LLScrollingPanelParamBase::weightToPercent( F32 weight )
+{
+	LLViewerVisualParam* param = mParam;
+	return (weight - param->getMinWeight()) /  (param->getMaxWeight() - param->getMinWeight()) * 100.f;
+}
+
+F32 LLScrollingPanelParamBase::percentToWeight( F32 percent )
+{
+	LLViewerVisualParam* param = mParam;
+	return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
+}
diff --git a/indra/newview/llscrollingpanelparambase.h b/indra/newview/llscrollingpanelparambase.h
new file mode 100644
index 0000000000000000000000000000000000000000..95388262514bc455c4e6f0170157d9c9c366fd37
--- /dev/null
+++ b/indra/newview/llscrollingpanelparambase.h
@@ -0,0 +1,62 @@
+/** 
+ * @file llscrollingpanelparam.h
+ * @brief the scrolling panel containing a list of visual param 
+ *  	  panels
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SCROLLINGPANELPARAMBASE_H
+#define LL_SCROLLINGPANELPARAMBASE_H
+
+#include "llpanel.h"
+#include "llscrollingpanellist.h"
+
+class LLViewerJointMesh;
+class LLViewerVisualParam;
+class LLWearable;
+class LLVisualParamHint;
+class LLViewerVisualParam;
+class LLJoint;
+
+class LLScrollingPanelParamBase : public LLScrollingPanel
+{
+public:
+	LLScrollingPanelParamBase( const LLPanel::Params& panel_params,
+				   LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints = FALSE );
+	virtual ~LLScrollingPanelParamBase();
+
+	virtual void		updatePanel(BOOL allow_modify);
+
+	static void			onSliderMoved(LLUICtrl* ctrl, void* userdata);
+
+	F32					weightToPercent( F32 weight );
+	F32					percentToWeight( F32 percent );
+
+public:
+	LLViewerVisualParam* mParam;
+protected:
+	BOOL mAllowModify;
+	LLWearable *mWearable;
+}; 
+
+#endif
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 363fe5f12b80f6a6b1453130458c183ae588ce7b..16729f045a0d4e91d1182b5a9b017b0af30e7f34 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -193,18 +193,28 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
 {
 	if (new_visibility["visible"].asBoolean())
 	{
-		bool is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
-		bool is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
+		const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
+		const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
 
 		if (is_outfit_edit_visible || is_wearable_edit_visible)
 		{
-			if (!gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
+			const LLWearable *wearable_ptr = mEditWearable->getWearable();
+			if (!wearable_ptr)
+			{
+				llwarns << "Visibility change to invalid wearable" << llendl;
+				return;
+			}
+			// Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar
+			// when editing its physics.
+			const BOOL disable_camera_motion = LLWearableType::getDisableCameraSwitch(wearable_ptr->getType());
+			if (!gAgentCamera.cameraCustomizeAvatar() && 
+				!disable_camera_motion &&
+				gSavedSettings.getBOOL("AppearanceCameraMovement"))
 			{
 				gAgentCamera.changeCameraToCustomizeAvatar();
 			}
 			if (is_wearable_edit_visible)
 			{
-				LLWearable *wearable_ptr = mEditWearable->getWearable();
 				if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
 				{
 					// we're no longer wearing the wearable we were last editing, switch back to outfit editor
@@ -289,7 +299,7 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel()
 {
 	toggleWearableEditPanel(FALSE);
 	toggleOutfitEditPanel(FALSE);
-	togglMyOutfitsPanel(TRUE);
+	toggleMyOutfitsPanel(TRUE);
 }
 
 void LLSidepanelAppearance::showOutfitEditPanel()
@@ -305,19 +315,28 @@ void LLSidepanelAppearance::showOutfitEditPanel()
 		mOutfitEdit->resetAccordionState();
 	}
 
-	togglMyOutfitsPanel(FALSE);
+	// If we're exiting the edit wearable view, and the camera was not focused on the avatar
+	// (e.g. such as if we were editing a physics param), then skip the outfits edit mode since
+	// otherwise this would trigger the camera focus mode.
+	if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar())
+	{
+		showOutfitsInventoryPanel();
+		return;
+	}
+
+	toggleMyOutfitsPanel(FALSE);
 	toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
 	toggleOutfitEditPanel(TRUE);
 }
 
-void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/)
+void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/, BOOL disable_camera_switch)
 {
-	togglMyOutfitsPanel(FALSE);
+	toggleMyOutfitsPanel(FALSE);
 	toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode
-	toggleWearableEditPanel(TRUE, wearable);
+	toggleWearableEditPanel(TRUE, wearable, disable_camera_switch);
 }
 
-void LLSidepanelAppearance::togglMyOutfitsPanel(BOOL visible)
+void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible)
 {
 	if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible)
 	{
@@ -390,7 +409,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we
 		{
 			gAgentCamera.changeCameraToCustomizeAvatar();
 		}
-		mEditWearable->setWearable(wearable);
+		mEditWearable->setWearable(wearable, disable_camera_switch);
 		mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency
 	}
 	else
@@ -434,14 +453,14 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
 }
 
 //static
-void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data)
+void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch)
 {
 	LLSideTray::getInstance()->showPanel("sidepanel_appearance");
 
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
 	if (panel)
 	{
-		panel->showWearableEditPanel(wearable);
+		panel->showWearableEditPanel(wearable, disable_camera_switch);
 	}
 }
 
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 2a83dfbc9d1eb5a4bd3a4cb2d66cc7a43b8abb36..6dd35202665663707e7911ff330d717273b6ddb0 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -51,7 +51,7 @@ public:
 
 	void refreshCurrentOutfitName(const std::string& name = "");
 
-	static void editWearable(LLWearable *wearable, LLView *data);
+	static void editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE);
 
 	void fetchInventory();
 	void inventoryFetched();
@@ -59,7 +59,7 @@ public:
 
 	void showOutfitsInventoryPanel();
 	void showOutfitEditPanel();
-	void showWearableEditPanel(LLWearable *wearable = NULL);
+	void showWearableEditPanel(LLWearable *wearable = NULL, BOOL disable_camera_switch = FALSE);
 	void setWearablesLoading(bool val);
 	void showDefaultSubpart();
 	void updateScrollingPanelList();
@@ -72,7 +72,7 @@ private:
 	void onOpenOutfitButtonClicked();
 	void onEditAppearanceButtonClicked();
 
-	void togglMyOutfitsPanel(BOOL visible);
+	void toggleMyOutfitsPanel(BOOL visible);
 	void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE);
 	void toggleWearableEditPanel(BOOL visible, LLWearable* wearable = NULL, BOOL disable_camera_switch = FALSE);
 
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 3c53e54203c889196be62a0590a015bd3a512fcb..ffe607f912aac5ae3bfed184fcab5107cbc544da 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -164,6 +164,12 @@ static bool handleAvatarLODChanged(const LLSD& newvalue)
 	return true;
 }
 
+static bool handleAvatarPhysicsLODChanged(const LLSD& newvalue)
+{
+	LLVOAvatar::sPhysicsLODFactor = (F32) newvalue.asReal();
+	return true;
+}
+
 static bool handleAvatarMaxVisibleChanged(const LLSD& newvalue)
 {
 	LLVOAvatar::sMaxVisible = (U32) newvalue.asInteger();
@@ -552,6 +558,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _2));
 	gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
 	gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2));
+	gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2));
 	gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2));
 	gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _2));
 	gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _2));
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index cc851e676b7035e3248e3d3684bedcea64e95775..519514d99cc45a726fbe3c11ee6691661b5499ce 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -89,6 +89,7 @@ public:
 		mInventoryItemsDict["New Skirt"]		= LLTrans::getString("New Skirt");
 		mInventoryItemsDict["New Alpha"]		= LLTrans::getString("New Alpha");
 		mInventoryItemsDict["New Tattoo"]		= LLTrans::getString("New Tattoo");
+		mInventoryItemsDict["New Physics"]		= LLTrans::getString("New Physics");
 		mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
 
 		mInventoryItemsDict["New Gesture"]		= LLTrans::getString("New Gesture");
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7c8f363f114c82a11a4e187312c1b549a0a524fd..bd46ee1b672a7cd9266d50f514b3713d8afd74a5 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3640,6 +3640,15 @@ class LLEnableEditShape : public view_listener_t
 	}
 };
 
+class LLEnableEditPhysics : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		//return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
+		return TRUE;
+	}
+};
+
 bool is_object_sittable()
 {
 	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
@@ -5526,6 +5535,11 @@ void handle_edit_shape()
 	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_shape"));
 }
 
+void handle_edit_physics()
+{
+	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_physics"));
+}
+
 void handle_report_abuse()
 {
 	// Prevent menu from appearing in screen shot.
@@ -7827,9 +7841,11 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
 	view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
 	view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+	view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
 	commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
 	commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
 	commit.add("EditShape", boost::bind(&handle_edit_shape));
+	commit.add("EditPhysics", boost::bind(&handle_edit_physics));
 
 	// View menu
 	view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2e376e8568e3dc88c4df379ebb53cbc3a85a660c..2c5e728c87d67feb37137b27f2b0bbe747ba847f 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -48,6 +48,7 @@
 #include "llanimationstates.h"
 #include "llavatarnamecache.h"
 #include "llavatarpropertiesprocessor.h"
+#include "llphysicsmotion.h"
 #include "llviewercontrol.h"
 #include "llcallingcard.h"		// IDEVO for LLAvatarTracker
 #include "lldrawpoolavatar.h"
@@ -108,6 +109,8 @@ extern F32 ANIM_SPEED_MIN;
 
 #include <boost/lexical_cast.hpp>
 
+// #define OUTPUT_BREAST_DATA
+
 using namespace LLVOAvatarDefines;
 
 //-----------------------------------------------------------------------------
@@ -123,6 +126,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"
 
 
 //-----------------------------------------------------------------------------
@@ -620,6 +624,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;
 
@@ -1144,6 +1149,7 @@ void LLVOAvatar::initClass()
 
 	gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise");
 	gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot");
+	gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion");
 	gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing");
 	gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye");
 	gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust");
@@ -1282,6 +1288,7 @@ void LLVOAvatar::initInstance(void)
 		// 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_FEMALE_WALK,				LLKeyframeWalkMotion::create );
@@ -1695,6 +1702,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 );
 
@@ -6211,11 +6219,9 @@ void LLVOAvatar::updateMeshTextures()
 			// When an avatar is changing clothes and not in Appearance mode,
 			// use the last-known good baked texture until it finish the first
 			// render of the new layerset.
-
 			const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet 
 										  && ( !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized()
 										  || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() );
-
 			use_lkg_baked_layer[i] = (!is_layer_baked[i] 
 									  && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) 
 									  && layerset_invalid);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index a779a1735c6f6fb952de98b69a238debbef64224..3659fb055f743f05ac9f22a4e7919c61c01a0b36 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -50,6 +50,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;
@@ -240,6 +241,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;
 
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 66a6ab5e94242a30cb0387196e1999856c46b550..92697fb2eb8334b4023801342cb168dd25d6b103 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -446,6 +446,7 @@ clothing_to_string_map_t init_clothing_string_map()
 	w_map.insert(std::make_pair(LLWearableType::WT_SKIRT, "skirt_not_worn"));
 	w_map.insert(std::make_pair(LLWearableType::WT_ALPHA, "alpha_not_worn"));
 	w_map.insert(std::make_pair(LLWearableType::WT_TATTOO, "tattoo_not_worn"));
+	w_map.insert(std::make_pair(LLWearableType::WT_PHYSICS, "physics_not_worn"));
 	return w_map;
 }
 
@@ -891,6 +892,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
 	setMenuItemVisible(menu, "edit",				!standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1);
 	setMenuItemEnabled(menu, "edit",				n_editable == 1 && n_worn == 1 && n_items == 1);
 	setMenuItemVisible(menu, "create_new",			mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
+	setMenuItemEnabled(menu, "create_new",			canAddWearables(ids));
 	setMenuItemVisible(menu, "show_original",		!standalone);
 	setMenuItemEnabled(menu, "show_original",		n_items == 1 && n_links == n_items);
 	setMenuItemVisible(menu, "take_off",			mask == MASK_CLOTHING && n_worn == n_items);
@@ -1041,6 +1043,10 @@ bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_id
 		U32 n_clothes					= m_it->second;
 
 		U32 wearable_count = gAgentWearables.getWearableCount(w_type);
+		if ((wearable_count > 0) && !LLWearableType::getAllowMultiwear(w_type))
+		{
+			return false;
+		}
 		if ((wearable_count + n_clothes) > LLAgentWearables::MAX_CLOTHING_PER_TYPE)
 		{
 			return false;
diff --git a/indra/newview/llwearabletype.cpp b/indra/newview/llwearabletype.cpp
index 0d707d65bf8d52f3762ef33ba81a1aa599f6fe97..f933be4d8f0f5e3f6860599a61391eb84b373cf0 100644
--- a/indra/newview/llwearabletype.cpp
+++ b/indra/newview/llwearabletype.cpp
@@ -34,25 +34,27 @@ struct WearableEntry : public LLDictionaryEntry
 	WearableEntry(const std::string &name,
 				  const std::string& default_new_name,
 				  LLAssetType::EType assetType,
-				  LLInventoryIcon::EIconName iconName);
+				  LLInventoryIcon::EIconName iconName,
+				  BOOL disable_camera_switch = FALSE,
+				  BOOL allow_multiwear = TRUE) :
+		LLDictionaryEntry(name),
+		mAssetType(assetType),
+		mDefaultNewName(default_new_name),
+		mLabel(LLTrans::getString(name)),
+		mIconName(iconName),
+		mDisableCameraSwitch(disable_camera_switch),
+		mAllowMultiwear(allow_multiwear)
+	{
+		
+	}
 	const LLAssetType::EType mAssetType;
 	const std::string mLabel;
 	const std::string mDefaultNewName; //keep mLabel for backward compatibility
 	LLInventoryIcon::EIconName mIconName;
+	BOOL mDisableCameraSwitch;
+	BOOL mAllowMultiwear;
 };
 
-WearableEntry::WearableEntry(const std::string &name,
-							 const std::string& default_new_name,
-							 LLAssetType::EType assetType,
-							 LLInventoryIcon::EIconName iconName) :
-	LLDictionaryEntry(name),
-	mAssetType(assetType),
-	mDefaultNewName(default_new_name),
-	mLabel(LLTrans::getString(name)),
-	mIconName(iconName)
-{
-}
-
 class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,
 							 public LLDictionary<LLWearableType::EType, WearableEntry>
 {
@@ -62,23 +64,26 @@ public:
 
 LLWearableDictionary::LLWearableDictionary()
 {
-	addEntry(LLWearableType::WT_SHAPE,        new WearableEntry("shape",       "New Shape",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_SHAPE));
-	addEntry(LLWearableType::WT_SKIN,         new WearableEntry("skin",        "New Skin",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_SKIN));
-	addEntry(LLWearableType::WT_HAIR,         new WearableEntry("hair",        "New Hair",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_HAIR));
-	addEntry(LLWearableType::WT_EYES,         new WearableEntry("eyes",        "New Eyes",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_EYES));
-	addEntry(LLWearableType::WT_SHIRT,        new WearableEntry("shirt",       "New Shirt",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SHIRT));
-	addEntry(LLWearableType::WT_PANTS,        new WearableEntry("pants",       "New Pants",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_PANTS));
-	addEntry(LLWearableType::WT_SHOES,        new WearableEntry("shoes",       "New Shoes",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SHOES));
-	addEntry(LLWearableType::WT_SOCKS,        new WearableEntry("socks",       "New Socks",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SOCKS));
-	addEntry(LLWearableType::WT_JACKET,       new WearableEntry("jacket",      "New Jacket",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_JACKET));
-	addEntry(LLWearableType::WT_GLOVES,       new WearableEntry("gloves",      "New Gloves",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_GLOVES));
-	addEntry(LLWearableType::WT_UNDERSHIRT,   new WearableEntry("undershirt",  "New Undershirt",	LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT));
-	addEntry(LLWearableType::WT_UNDERPANTS,   new WearableEntry("underpants",  "New Underpants",	LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS));
-	addEntry(LLWearableType::WT_SKIRT,        new WearableEntry("skirt",       "New Skirt",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SKIRT));
-	addEntry(LLWearableType::WT_ALPHA,        new WearableEntry("alpha",       "New Alpha",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_ALPHA));
-	addEntry(LLWearableType::WT_TATTOO,       new WearableEntry("tattoo",      "New Tattoo",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_TATTOO));
-	addEntry(LLWearableType::WT_INVALID,      new WearableEntry("invalid",     "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryIcon::ICONNAME_INVALID));
-	addEntry(LLWearableType::WT_NONE,      	  new WearableEntry("none",        "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryIcon::ICONNAME_INVALID));
+	addEntry(LLWearableType::WT_SHAPE,        new WearableEntry("shape",       "New Shape",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
+	addEntry(LLWearableType::WT_SKIN,         new WearableEntry("skin",        "New Skin",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
+	addEntry(LLWearableType::WT_HAIR,         new WearableEntry("hair",        "New Hair",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
+	addEntry(LLWearableType::WT_EYES,         new WearableEntry("eyes",        "New Eyes",			LLAssetType::AT_BODYPART, 	LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE));
+	addEntry(LLWearableType::WT_SHIRT,        new WearableEntry("shirt",       "New Shirt",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
+	addEntry(LLWearableType::WT_PANTS,        new WearableEntry("pants",       "New Pants",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
+	addEntry(LLWearableType::WT_SHOES,        new WearableEntry("shoes",       "New Shoes",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
+	addEntry(LLWearableType::WT_SOCKS,        new WearableEntry("socks",       "New Socks",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
+	addEntry(LLWearableType::WT_JACKET,       new WearableEntry("jacket",      "New Jacket",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
+	addEntry(LLWearableType::WT_GLOVES,       new WearableEntry("gloves",      "New Gloves",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
+	addEntry(LLWearableType::WT_UNDERSHIRT,   new WearableEntry("undershirt",  "New Undershirt",	LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
+	addEntry(LLWearableType::WT_UNDERPANTS,   new WearableEntry("underpants",  "New Underpants",	LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
+	addEntry(LLWearableType::WT_SKIRT,        new WearableEntry("skirt",       "New Skirt",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
+	addEntry(LLWearableType::WT_ALPHA,        new WearableEntry("alpha",       "New Alpha",			LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
+	addEntry(LLWearableType::WT_TATTOO,       new WearableEntry("tattoo",      "New Tattoo",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
+
+	addEntry(LLWearableType::WT_PHYSICS,      new WearableEntry("physics",     "New Physics",		LLAssetType::AT_CLOTHING, 	LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE));
+
+	addEntry(LLWearableType::WT_INVALID,      new WearableEntry("invalid",     "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
+	addEntry(LLWearableType::WT_NONE,      	  new WearableEntry("none",        "Invalid Wearable", 	LLAssetType::AT_NONE, 		LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
 }
 
 // static
@@ -134,3 +139,19 @@ LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType typ
 	return entry->mIconName;
 } 
 
+// static 
+BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
+{
+	const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
+	const WearableEntry *entry = dict->lookup(type);
+	return entry->mDisableCameraSwitch;
+}
+
+// static 
+BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
+{
+	const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
+	const WearableEntry *entry = dict->lookup(type);
+	return entry->mAllowMultiwear;
+}
+
diff --git a/indra/newview/llwearabletype.h b/indra/newview/llwearabletype.h
index 3bbf8ba0bdc92d47ebb8d9f170b713503e257d02..d633b4807ece113c630fca0250318a5d86a338fe 100644
--- a/indra/newview/llwearabletype.h
+++ b/indra/newview/llwearabletype.h
@@ -52,7 +52,8 @@ public:
 		WT_SKIRT	  = 12,
 		WT_ALPHA	  = 13,
 		WT_TATTOO	  = 14,
-		WT_COUNT	  = 15,
+		WT_PHYSICS	  = 15,
+		WT_COUNT	  = 16,
 
 		WT_INVALID	  = 255,
 		WT_NONE		  = -1,
@@ -64,6 +65,8 @@ public:
 	static LLAssetType::EType 			getAssetType(EType type);
 	static EType 						typeNameToType(const std::string& type_name);
 	static LLInventoryIcon::EIconName 	getIconName(EType type);
+	static BOOL 						getDisableCameraSwitch(EType type);
+	static BOOL 						getAllowMultiwear(EType type);
 
 protected:
 	LLWearableType() {}
diff --git a/indra/newview/skins/default/textures/icons/Inv_Physics.png b/indra/newview/skins/default/textures/icons/Inv_Physics.png
new file mode 100644
index 0000000000000000000000000000000000000000..ddd36b446b1e72d9faec4952b3b7b202646a049c
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Physics.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index d79d6607244c7a62a9ed3c2ac2747b5af83e2a5a..1ca48b01a89b884167053810e7cc42c14fbe09ea 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -226,6 +226,7 @@ with the same filename but different name
   <texture name="Inv_SysClosed" file_name="icons/Inv_SysClosed.png" preload="false" />
   <texture name="Inv_SysOpen" file_name="icons/Inv_SysOpen.png" preload="false" />
   <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
+  <texture name="Inv_Physics" file_name="icons/Inv_Physics.png" preload="false" />
   <texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
   <texture name="Inv_TrashClosed" file_name="icons/Inv_TrashClosed.png" preload="false" />
   <texture name="Inv_TrashOpen" file_name="icons/Inv_TrashOpen.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index d727294cc8ebf23ff96af095c4d55c65d982936e..d9bdfece383b82c4f4188628694e1e0275c71a2e 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -150,6 +150,18 @@
                      function="Edit.EnableTakeOff"
                      parameter="tattoo" />
                 </menu_item_call>
+               <menu_item_call
+                 enabled="false"
+                 label="Physics"
+                 layout="topleft"
+                 name="Self Physics">
+                    <menu_item_call.on_click
+                     function="Edit.TakeOff"
+                     parameter="physics" />
+                    <menu_item_call.on_enable
+                     function="Edit.EnableTakeOff"
+                     parameter="physics" />
+                </menu_item_call>
                <menu_item_call
                  enabled="false"
                  label="Alpha"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index c0046d8e2834bed314670daa691bd936c407c13a..e91f4458aee8d9c2954530f720fd577abba7fcb0 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -200,6 +200,14 @@
              function="Inventory.DoCreate"
              parameter="tattoo" />
         </menu_item_call>
+        <menu_item_call
+         label="New Physics"
+         layout="topleft"
+         name="New Physics">
+            <menu_item_call.on_click
+             function="Inventory.DoCreate"
+             parameter="physics" />
+        </menu_item_call>
     </menu>
     <menu
      label="New Body Parts"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index ae98abf4fbce4403f1c93771d9549d8ed1428438..90e8db370910d601917395f20a48d98e19e24cce 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -188,6 +188,14 @@
                      function="Inventory.DoCreate"
                      parameter="tattoo" />
                 </menu_item_call>
+                <menu_item_call
+                 label="New Physics"
+                 layout="topleft"
+                 name="New Physics">
+                    <menu_item_call.on_click
+                     function="Inventory.DoCreate"
+                     parameter="physics" />
+                </menu_item_call>
             </menu>
             <menu
              height="85"
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 5fc25b8f0f9c68b738b7297f07c3fff6473d7952..fc7272b9047f8e5073d2bbfaae90abb9408fb6f2 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -132,6 +132,14 @@
                      function="Gear.Create"
                      parameter="alpha" />
                 </menu_item_call>
+                <menu_item_call
+                 label="New Physics"
+                 layout="topleft"
+                 name="New Physics">
+                    <menu_item_call.on_click
+                     function="Gear.Create"
+                     parameter="physics" />
+                </menu_item_call>
                 <menu_item_call
                  label="New Tattoo"
                  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 934cae93db0f83e8f75b2bca8a93ec67d865dcb6..51610c0ae03d83077520b41c8b114b58a293769c 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3428,6 +3428,16 @@
                  function="Edit.EnableTakeOff"
                  parameter="tattoo" />
             </menu_item_call>
+            <menu_item_call
+             label="Physics"
+             name="Physics">
+                <menu_item_call.on_click
+                 function="Edit.TakeOff"
+                 parameter="physics" />
+                <menu_item_call.on_enable
+                 function="Edit.EnableTakeOff"
+                 parameter="physics" />
+            </menu_item_call>
             <menu_item_call
              label="All Clothes"
              name="All Clothes">
diff --git a/indra/newview/skins/default/xui/en/panel_edit_physics.xml b/indra/newview/skins/default/xui/en/panel_edit_physics.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c6f974f4f1d30dbad1f34cb801a5833506052cd6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_physics.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+     background_visible="true"
+	 follows="all"
+	 height="400"
+	 layout="topleft"
+	 left="0"
+	 name="edit_physics_panel"
+	 top_pad="10"
+	 width="333" >
+     <panel
+         border="false"
+         bg_alpha_color="DkGray2"
+         bg_opaque_color="DkGray2"
+         background_visible="true"
+         background_opaque="true"
+         follows="all"
+         height="388"
+         label=""
+         layout="topleft"
+		 left="10"
+         name="accordion_panel"
+		 top_pad="0"
+         width="313">
+     <accordion
+        follows="all"
+        height ="388"
+        layout="topleft"
+        left="0"
+	single_expansion="true"
+        fit_parent="true"
+        name="physics_accordion"
+        top="0"
+        width="313">
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_breasts_updown_tab"
+			title="Breasts Bounce">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="10"
+				name="physics_breasts_updown_param_list"
+				top="10"
+				width="303" />
+		</accordion_tab>
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_breasts_inout_tab"
+			title="Breasts Cleavage">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="0"
+				name="physics_breasts_inout_param_list"
+				top_pad="50"
+				width="303" />
+		</accordion_tab>
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_belly_tab"
+			title="Belly Bounce">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="0"
+				name="physics_belly_updown_param_list"
+				top_pad="40"
+				width="303" />
+		</accordion_tab>
+
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_butt_tab"
+			title="Butt Bounce">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="0"
+				name="physics_butt_updown_param_list"
+				top_pad="30"
+				width="303" />
+		</accordion_tab>
+
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_butt_leftright_tab"
+			title="Butt Sway">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="0"
+				name="physics_butt_leftright_param_list"
+				top_pad="20"
+				width="303" />
+		</accordion_tab>
+		<accordion_tab
+			layout="topleft"
+			fit_panel="false"
+			min_height="50"
+			name="physics_advanced_tab"
+			title="Advanced Parameters">
+			<scrolling_panel_list
+				follows="all"
+				layout="topleft"
+				left="0"
+				name="physics_advanced_param_list"
+				top_pad="10"
+				width="303" />
+		</accordion_tab>
+	</accordion>
+    </panel>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index ac8917d272d9364d12563200e33c52a1cd0777eb..c8764a6a8439501720773449f656b2e692e4c456 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -71,6 +71,10 @@
      name="edit_tattoo_title">
         Editing Tattoo
     </string>
+    <string
+     name="edit_physics_title">
+        Editing Physics
+    </string>
     <string
      name="shape_desc_text">
         Shape:
@@ -131,6 +135,10 @@
      name="tattoo_desc_text">
         Tattoo:
     </string>
+    <string
+     name="physics_desc_text">
+        Physics:
+    </string>
     <!-- Default width of the button should be to show it without label.
      Button will be extedned in code to show whole label when wearable is being changed.
     -->
@@ -410,6 +418,16 @@
          top="8"
          visible="false"
          width="333" />
+        <panel
+         filename="panel_edit_physics.xml"
+         follows="all"
+         height="425"
+         layout="topleft"
+         left="0"
+         name="edit_physics_panel"
+         top="8"
+         visible="false"
+         width="333" />
     </panel>
     <panel
      follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 6573822d1a1b493a5da26081806d590e2b4eab78..d74197d965b59833a5437d0923a9c73c990eb4b3 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -2,7 +2,7 @@
 <panel
  border="true"
  follows="left|top|right|bottom"
- height="408"
+ height="418"
  label="Graphics"
  layout="topleft"
  left="102"
@@ -327,6 +327,37 @@
              value="4"/>
         </combo_box>
     
+        <slider
+        control_name="RenderAvatarPhysicsLODFactor"
+        follows="left|top"
+        height="16"
+        initial_value="100"
+	increment=".05"
+        label="  Avatar Physics:"
+        label_width="85"
+        layout="topleft"
+        left_delta="-16"
+        name="AvatarPhysicsDetail"
+        show_text="false"
+        top_pad="12"
+        width="160">
+           <slider.commit_callback
+            function="Pref.UpdateSliderText"
+            parameter="AvatarPhysicsDetailText" />
+        </slider>
+        <text
+        type="string"
+        length="1"
+        follows="left|top"
+        height="12"
+        layout="topleft"
+        left_delta="165"
+        name="AvatarPhysicsDetailText"
+        top_pad="-16"
+        width="128">
+           Low
+        </text>
+
 		<slider
 		 control_name="RenderFarClip"
 		 decimal_digits="0"
@@ -618,6 +649,7 @@
          width="128">
             Low
         </text>
+
         <text
          type="string"
          length="1"
@@ -628,7 +660,7 @@
          name="AvatarRenderingText"
          top_pad="18"
          width="128">
-            Avatar rendering:
+        Avatar Rendering:
       </text>
       <check_box
        control_name="RenderUseImpostors"
@@ -672,7 +704,7 @@
        left="358"
        left_pad="-30"
        name="TerrainDetailText"
-       top="226"
+        top="250"
        width="155">
           Terrain detail:
       </text>
@@ -710,7 +742,7 @@
      layout="topleft"
      left="10"
      name="Apply"
-     top="383"
+     top="390"
      width="115">
         <button.commit_callback
          function="Pref.Apply" />
@@ -722,7 +754,7 @@
      layout="topleft"
      left_pad="3"
      name="Defaults"
-     top="383"
+     top="390"
      width="115">
         <button.commit_callback
          function="Pref.HardwareDefaults" />
diff --git a/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1351f75623e96293c4e3027cc7c972dfb010aa44
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ layout="topleft"
+ left="0"
+ name="LLScrollingPanelParamBase"
+ height="16"
+ width="290">
+    <slider
+     can_edit_text="true"
+     decimal_digits="0"
+     enabled="false"
+     height="12"
+     increment="1"
+     initial_value="0"
+     label="[DESC]"
+     label_width="125"
+     layout="bottom|left"
+     left="16"
+     max_val="100"
+     name="param slider"
+     bottom="0"
+     width="264"
+     />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 14ea43a8f80b5a85c39320ce07a299ac058aec24..ed7814e0f0932779b8c10b754677d42e8fecec59 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1853,6 +1853,7 @@ Requests name of an avatar.  When data is available the dataserver event will be
 	<string name="skirt">Skirt</string>
 	<string name="alpha">Alpha</string>
 	<string name="tattoo">Tattoo</string>
+  <string name="physics">Physics</string>
   <string name="invalid">invalid</string>
   <string name="none">none</string>
   
@@ -1868,6 +1869,7 @@ Requests name of an avatar.  When data is available the dataserver event will be
 	<string name="skirt_not_worn">Skirt not worn</string>
 	<string name="alpha_not_worn">Alpha not worn</string>
 	<string name="tattoo_not_worn">Tattoo not worn</string>
+  <string name="physics_not_worn">Physics not worn</string>
 	<string name="invalid_not_worn">invalid</string>
 
 	<!-- Create new wearable of the specified type -->
@@ -1886,6 +1888,7 @@ Requests name of an avatar.  When data is available the dataserver event will be
 	<string name="create_new_skirt">Create new skirt</string>
 	<string name="create_new_alpha">Create new alpha</string>
 	<string name="create_new_tattoo">Create new tattoo</string>
+  <string name="create_new_physics">Create new physics</string>
 	<string name="create_new_invalid">invalid</string>
 
   <!-- Wearable List-->
@@ -2497,8 +2500,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 <string name="Body Thin">Body Thin</string>
 
 <string name="Bow Legged">Bow Legged</string>
-<string name="Breast Buoyancy">Breast Buoyancy</string>
-<string name="Breast Cleavage">Breast Cleavage</string>
+<string name="Breast Physics UpDown Controller">Breast Buoyancy</string>
+<string name="Breast Physics InOut Controller">Breast Cleavage</string>
 <string name="Breast Size">Breast Size</string>
 <string name="Bridge Width">Bridge Width</string>
 <string name="Broad">Broad</string>
@@ -2508,10 +2511,52 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 <string name="Bulbous">Bulbous</string>
 <string name="Bulbous Nose">Bulbous Nose</string>
 
+<string name="Breast Physics Mass">Breast Mass</string>
+<string name="Breast Physics Smoothing">Breast Smoothing</string>
+<string name="Breast Physics Gravity">Breast Gravity</string>
+
+<string name="Breast Physics InOut Max Speed">Max Effect</string>
+<string name="Breast Physics InOut Spring">Spring</string>
+<string name="Breast Physics InOut Gain">Gain</string>
+<string name="Breast Physics InOut Damping">Damping</string>
+<string name="Breast Physics InOut Drag">Breast Cleavage Drag</string>
+
+<string name="Breast Physics UpDown Max Speed">Max Effect</string>
+<string name="Breast Physics UpDown Spring">Spring</string>
+<string name="Breast Physics UpDown Gain">Gain</string>
+<string name="Breast Physics UpDown Damping">Damping</string>
+<string name="Breast Physics UpDown Drag">Breast Bounce Drag</string>
+
+<string name="Belly Physics Mass">Belly Mass</string>
+<string name="Belly Physics Smoothing">Belly Smoothing</string>
+<string name="Belly Physics Gravity">Belly Gravity</string>
+
+<string name="Belly Physics UpDown Max Speed">Max Effect</string>
+<string name="Belly Physics UpDown Spring">Spring</string>
+<string name="Belly Physics UpDown Gain">Gain</string>
+<string name="Belly Physics UpDown Damping">Damping</string>
+<string name="Belly Physics UpDown Drag">Belly Bounce Drag</string>
+
+<string name="Butt Physics Mass">Butt Mass</string>
+<string name="Butt Physics Smoothing">Butt Smoothing</string>
+<string name="Butt Physics Gravity">Butt Gravity</string>
+
+<string name="Butt Physics UpDown Max Speed">Max Effect</string>
+<string name="Butt Physics UpDown Spring">Spring</string>
+<string name="Butt Physics UpDown Gain">Gain</string>
+<string name="Butt Physics UpDown Damping">Damping</string>
+<string name="Butt Physics UpDown Drag">Butt Bounce Drag</string>
+
+<string name="Butt Physics LeftRight Max Speed">Max Effect</string>
+<string name="Butt Physics LeftRight Spring">Spring</string>
+<string name="Butt Physics LeftRight Gain">Gain</string>
+<string name="Butt Physics LeftRight Damping">Damping</string>
+<string name="Butt Physics LeftRight Drag">Butt Sway Drag</string>
 
 <string name="Bushy Eyebrows">Bushy Eyebrows</string>
 <string name="Bushy Hair">Bushy Hair</string>
 <string name="Butt Size">Butt Size</string>
+<string name="Butt Gravity">Butt Gravity</string>
 <string name="bustle skirt">Bustle Skirt</string>
 <string name="no bustle">No Bustle</string>
 <string name="more bustle">More Bustle</string>
@@ -3215,6 +3260,7 @@ Abuse Report</string>
   <string name="New Skirt">New Skirt</string>
   <string name="New Alpha">New Alpha</string>
   <string name="New Tattoo">New Tattoo</string>
+  <string name="New Physics">New Physics</string>
   <string name="Invalid Wearable">Invalid Wearable</string>
   <string name="New Gesture">New Gesture</string>
   <string name="New Script">New Script</string>