aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie2012-08-14 02:34:03 +0100
committerMelanie2012-08-14 02:34:03 +0100
commit9b014a71679b6697954eb446be9f3d7c2e0a61b9 (patch)
treea454037938403aa76339b021dab93af98fab1bf2
parentMerge branch 'avination' into ubitwork (diff)
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-9b014a71679b6697954eb446be9f3d7c2e0a61b9.zip
opensim-SC_OLD-9b014a71679b6697954eb446be9f3d7c2e0a61b9.tar.gz
opensim-SC_OLD-9b014a71679b6697954eb446be9f3d7c2e0a61b9.tar.bz2
opensim-SC_OLD-9b014a71679b6697954eb446be9f3d7c2e0a61b9.tar.xz
Merge branch 'careminster' into avination
Conflicts: OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
-rw-r--r--OpenSim/Framework/Serialization/External/LandDataSerializer.cs22
-rw-r--r--OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs85
-rw-r--r--OpenSim/Region/Application/OpenSim.cs15
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs49
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs126
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs80
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs168
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs64
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs18
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs114
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs206
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs100
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs77
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs76
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs3
-rw-r--r--bin/OpenSimDefaults.ini44
-rwxr-xr-xbin/lib32/BulletSim.dllbin533504 -> 534016 bytes
-rwxr-xr-xbin/lib32/libBulletSim.sobin2340496 -> 2345796 bytes
-rwxr-xr-xbin/lib64/BulletSim.dllbin684032 -> 685056 bytes
-rwxr-xr-xbin/lib64/libBulletSim.sobin2540931 -> 2551398 bytes
29 files changed, 871 insertions, 431 deletions
diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
index a64f01c..709b516 100644
--- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
@@ -93,6 +93,8 @@ namespace OpenSim.Framework.Serialization.External
93 "MediaURL", (ld, xtr) => ld.MediaURL = xtr.ReadElementString("MediaURL")); 93 "MediaURL", (ld, xtr) => ld.MediaURL = xtr.ReadElementString("MediaURL"));
94 m_ldProcessors.Add( 94 m_ldProcessors.Add(
95 "MusicURL", (ld, xtr) => ld.MusicURL = xtr.ReadElementString("MusicURL")); 95 "MusicURL", (ld, xtr) => ld.MusicURL = xtr.ReadElementString("MusicURL"));
96 m_ldProcessors.Add(
97 "OwnerID", (ld, xtr) => ld.OwnerID = UUID.Parse(xtr.ReadElementString("OwnerID")));
96 98
97 m_ldProcessors.Add( 99 m_ldProcessors.Add(
98 "ParcelAccessList", ProcessParcelAccessList); 100 "ParcelAccessList", ProcessParcelAccessList);
@@ -186,7 +188,16 @@ namespace OpenSim.Framework.Serialization.External
186 return landData; 188 return landData;
187 } 189 }
188 190
189 public static string Serialize(LandData landData) 191 /// <summary>
192 /// Serialize land data
193 /// </summary>
194 /// <param name='landData'></param>
195 /// <param name='options'>
196 /// Serialization options.
197 /// Can be null if there are no options.
198 /// "wipe-owners" will write UUID.Zero rather than the ownerID so that a later reload loads all parcels with the estate owner as the owner
199 /// </param>
200 public static string Serialize(LandData landData, Dictionary<string, object> options)
190 { 201 {
191 StringWriter sw = new StringWriter(); 202 StringWriter sw = new StringWriter();
192 XmlTextWriter xtw = new XmlTextWriter(sw); 203 XmlTextWriter xtw = new XmlTextWriter(sw);
@@ -215,7 +226,14 @@ namespace OpenSim.Framework.Serialization.External
215 xtw.WriteElementString("MediaID", landData.MediaID.ToString()); 226 xtw.WriteElementString("MediaID", landData.MediaID.ToString());
216 xtw.WriteElementString("MediaURL", landData.MediaURL); 227 xtw.WriteElementString("MediaURL", landData.MediaURL);
217 xtw.WriteElementString("MusicURL", landData.MusicURL); 228 xtw.WriteElementString("MusicURL", landData.MusicURL);
218 xtw.WriteElementString("OwnerID", landData.OwnerID.ToString()); 229
230 UUID ownerIdToWrite;
231 if (options != null && options.ContainsKey("wipe-owners"))
232 ownerIdToWrite = UUID.Zero;
233 else
234 ownerIdToWrite = landData.OwnerID;
235
236 xtw.WriteElementString("OwnerID", ownerIdToWrite.ToString());
219 237
220 xtw.WriteStartElement("ParcelAccessList"); 238 xtw.WriteStartElement("ParcelAccessList");
221 foreach (LandAccessEntry pal in landData.ParcelAccessList) 239 foreach (LandAccessEntry pal in landData.ParcelAccessList)
diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
index b8ed9e1..8b9756b 100644
--- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
@@ -42,22 +42,23 @@ namespace OpenSim.Framework.Serialization.Tests
42 private LandData land; 42 private LandData land;
43 private LandData landWithParcelAccessList; 43 private LandData landWithParcelAccessList;
44 44
45 private static string preSerialized = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList />\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>"; 45// private static string preSerialized = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList />\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>";
46 private static string preSerializedWithParcelAccessList = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList>\n <ParcelAccessEntry>\n <AgentID>62d65d45-c91a-4f77-862c-46557d978b6c</AgentID>\n <Time>0</Time>\n <AccessList>2</AccessList>\n </ParcelAccessEntry>\n <ParcelAccessEntry>\n <AgentID>ec2a8d18-2378-4fe0-8b68-2a31b57c481e</AgentID>\n <Time>0</Time>\n <AccessList>1</AccessList>\n </ParcelAccessEntry>\n </ParcelAccessList>\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>"; 46 private static string preSerializedWithParcelAccessList
47 = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList>\n <ParcelAccessEntry>\n <AgentID>62d65d45-c91a-4f77-862c-46557d978b6c</AgentID>\n <Time>0</Time>\n <AccessList>2</AccessList>\n </ParcelAccessEntry>\n <ParcelAccessEntry>\n <AgentID>ec2a8d18-2378-4fe0-8b68-2a31b57c481e</AgentID>\n <Time>0</Time>\n <AccessList>1</AccessList>\n </ParcelAccessEntry>\n </ParcelAccessList>\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>";
47 48
48 [SetUp] 49 [SetUp]
49 public void setup() 50 public void setup()
50 { 51 {
51 // setup LandData object 52 // setup LandData object
52 this.land = new LandData(); 53 this.land = new LandData();
53 this.land.AABBMax = new Vector3(0, 0, 0); 54 this.land.AABBMax = new Vector3(1, 2, 3);
54 this.land.AABBMin = new Vector3(128, 128, 128); 55 this.land.AABBMin = new Vector3(129, 130, 131);
55 this.land.Area = 128; 56 this.land.Area = 128;
56 this.land.AuctionID = 0; 57 this.land.AuctionID = 4;
57 this.land.AuthBuyerID = new UUID(); 58 this.land.AuthBuyerID = new UUID("7176df0c-6c50-45db-8a37-5e78be56a0cd");
58 this.land.Category = ParcelCategory.Residential; 59 this.land.Category = ParcelCategory.Residential;
59 this.land.ClaimDate = 0; 60 this.land.ClaimDate = 1;
60 this.land.ClaimPrice = 0; 61 this.land.ClaimPrice = 2;
61 this.land.GlobalID = new UUID("54ff9641-dd40-4a2c-b1f1-47dd3af24e50"); 62 this.land.GlobalID = new UUID("54ff9641-dd40-4a2c-b1f1-47dd3af24e50");
62 this.land.GroupID = new UUID("d740204e-bbbf-44aa-949d-02c7d739f6a5"); 63 this.land.GroupID = new UUID("d740204e-bbbf-44aa-949d-02c7d739f6a5");
63 this.land.Description = "land data to test LandDataSerializer"; 64 this.land.Description = "land data to test LandDataSerializer";
@@ -65,7 +66,7 @@ namespace OpenSim.Framework.Serialization.Tests
65 this.land.LandingType = (byte)LandingType.Direct; 66 this.land.LandingType = (byte)LandingType.Direct;
66 this.land.Name = "LandDataSerializerTest Land"; 67 this.land.Name = "LandDataSerializerTest Land";
67 this.land.Status = ParcelStatus.Leased; 68 this.land.Status = ParcelStatus.Leased;
68 this.land.LocalID = 0; 69 this.land.LocalID = 1;
69 this.land.MediaAutoScale = (byte)0x01; 70 this.land.MediaAutoScale = (byte)0x01;
70 this.land.MediaID = new UUID("d4452578-2f25-4b97-a81b-819af559cfd7"); 71 this.land.MediaID = new UUID("d4452578-2f25-4b97-a81b-819af559cfd7");
71 this.land.MediaURL = "http://videos.opensimulator.org/bumblebee.mp4"; 72 this.land.MediaURL = "http://videos.opensimulator.org/bumblebee.mp4";
@@ -90,26 +91,26 @@ namespace OpenSim.Framework.Serialization.Tests
90 /// <summary> 91 /// <summary>
91 /// Test the LandDataSerializer.Serialize() method 92 /// Test the LandDataSerializer.Serialize() method
92 /// </summary> 93 /// </summary>
93 [Test] 94// [Test]
94 public void LandDataSerializerSerializeTest() 95// public void LandDataSerializerSerializeTest()
95 { 96// {
96 TestHelpers.InMethod(); 97// TestHelpers.InMethod();
97 98//
98 string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n"); 99// string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n");
99 Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string"); 100// Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string");
100 101//
101 // adding a simple boolean variable because resharper nUnit integration doesn't like this 102// // adding a simple boolean variable because resharper nUnit integration doesn't like this
102 // XML data in the Assert.That statement. Not sure why. 103// // XML data in the Assert.That statement. Not sure why.
103 bool result = (serialized == preSerialized); 104// bool result = (serialized == preSerialized);
104 Assert.That(result, "result of Serialize LandData does not match expected result"); 105// Assert.That(result, "result of Serialize LandData does not match expected result");
105 106//
106 string serializedWithParcelAccessList = LandDataSerializer.Serialize(this.landWithParcelAccessList).Replace("\r\n", "\n"); 107// string serializedWithParcelAccessList = LandDataSerializer.Serialize(this.landWithParcelAccessList).Replace("\r\n", "\n");
107 Assert.That(serializedWithParcelAccessList.Length > 0, 108// Assert.That(serializedWithParcelAccessList.Length > 0,
108 "Serialize(LandData) returned empty string for LandData object with ParcelAccessList"); 109// "Serialize(LandData) returned empty string for LandData object with ParcelAccessList");
109 result = (serializedWithParcelAccessList == preSerializedWithParcelAccessList); 110// result = (serializedWithParcelAccessList == preSerializedWithParcelAccessList);
110 Assert.That(result, 111// Assert.That(result,
111 "result of Serialize(LandData) does not match expected result (pre-serialized with parcel access list"); 112// "result of Serialize(LandData) does not match expected result (pre-serialized with parcel access list");
112 } 113// }
113 114
114 /// <summary> 115 /// <summary>
115 /// Test the LandDataSerializer.Deserialize() method 116 /// Test the LandDataSerializer.Deserialize() method
@@ -120,10 +121,28 @@ namespace OpenSim.Framework.Serialization.Tests
120 TestHelpers.InMethod(); 121 TestHelpers.InMethod();
121// log4net.Config.XmlConfigurator.Configure(); 122// log4net.Config.XmlConfigurator.Configure();
122 123
123 LandData ld = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerialized); 124 LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, null));
124 Assert.That(ld != null, "Deserialize(string) returned null"); 125 Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null");
125 Assert.That(ld.GlobalID == this.land.GlobalID, "Reified LandData.GlobalID != original LandData.GlobalID"); 126// Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax));
126 Assert.That(ld.Name == this.land.Name, "Reified LandData.Name != original LandData.Name"); 127// Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin));
128 Assert.That(ld.Area, Is.EqualTo(land.Area));
129 Assert.That(ld.AuctionID, Is.EqualTo(land.AuctionID));
130 Assert.That(ld.AuthBuyerID, Is.EqualTo(land.AuthBuyerID));
131 Assert.That(ld.Category, Is.EqualTo(land.Category));
132 Assert.That(ld.ClaimDate, Is.EqualTo(land.ClaimDate));
133 Assert.That(ld.ClaimPrice, Is.EqualTo(land.ClaimPrice));
134 Assert.That(ld.GlobalID, Is.EqualTo(land.GlobalID), "Reified LandData.GlobalID != original LandData.GlobalID");
135 Assert.That(ld.GroupID, Is.EqualTo(land.GroupID));
136 Assert.That(ld.Description, Is.EqualTo(land.Description));
137 Assert.That(ld.Flags, Is.EqualTo(land.Flags));
138 Assert.That(ld.LandingType, Is.EqualTo(land.LandingType));
139 Assert.That(ld.Name, Is.EqualTo(land.Name), "Reified LandData.Name != original LandData.Name");
140 Assert.That(ld.Status, Is.EqualTo(land.Status));
141 Assert.That(ld.LocalID, Is.EqualTo(land.LocalID));
142 Assert.That(ld.MediaAutoScale, Is.EqualTo(land.MediaAutoScale));
143 Assert.That(ld.MediaID, Is.EqualTo(land.MediaID));
144 Assert.That(ld.MediaURL, Is.EqualTo(land.MediaURL));
145 Assert.That(ld.OwnerID, Is.EqualTo(land.OwnerID));
127 } 146 }
128 147
129 [Test] 148 [Test]
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index ba8aa9f..6255515 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -294,14 +294,13 @@ namespace OpenSim
294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", 294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
295 "Save a region's data to an OAR archive.", 295 "Save a region's data to an OAR archive.",
296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
297 "-h|--home=<url> adds the url of the profile service to the saved user information." + Environment.NewLine 297 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
298 + "--noassets stops assets being saved to the OAR." + Environment.NewLine 298 + "--noassets stops assets being saved to the OAR.\n"
299 + "--publish saves an OAR stripped of owner and last owner information." + Environment.NewLine 299 + "--publish saves an OAR stripped of owner and last owner information.\n"
300 + " on reload, the estate owner will be the owner of all objects" + Environment.NewLine 300 + " on reload, the estate owner will be the owner of all objects\n"
301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published" + Environment.NewLine 301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
302 + " this option is EXPERIMENTAL" + Environment.NewLine 302 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
303 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine 303 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
304 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
305 + "The OAR path must be a filesystem path." 304 + "The OAR path must be a filesystem path."
306 + " If this is not given then the oar is saved to region.oar in the current directory.", 305 + " If this is not given then the oar is saved to region.oar in the current directory.",
307 SaveOar); 306 SaveOar);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index d397893..88c4d7f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -126,9 +126,14 @@ namespace OpenSim.Region.ClientStack.Linden
126 IConfig sconfig = config.Configs["Startup"]; 126 IConfig sconfig = config.Configs["Startup"];
127 if (sconfig != null) 127 if (sconfig != null)
128 { 128 {
129 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
130 m_levelUpload = sconfig.GetInt("LevelUpload", 0); 129 m_levelUpload = sconfig.GetInt("LevelUpload", 0);
131 } 130 }
131
132 IConfig appearanceConfig = config.Configs["Appearance"];
133 if (appearanceConfig != null)
134 {
135 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
136 }
132 } 137 }
133 138
134 m_assetService = m_Scene.AssetService; 139 m_assetService = m_Scene.AssetService;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index b3d61a8..6aac591 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -66,9 +66,9 @@ namespace OpenSim.Region.ClientStack.Linden
66 66
67 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
68 { 68 {
69 IConfig sconfig = source.Configs["Startup"]; 69 IConfig appearanceConfig = source.Configs["Appearance"];
70 if (sconfig != null) 70 if (appearanceConfig != null)
71 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 71 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
72 } 72 }
73 73
74 public void AddRegion(Scene s) 74 public void AddRegion(Scene s)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index b588704..88ca9db 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -284,7 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
284 sp.ClearAttachments(); 284 sp.ClearAttachments();
285 } 285 }
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
288 { 288 {
289 lock (sp.AttachmentsSyncLock) 289 lock (sp.AttachmentsSyncLock)
290 { 290 {
@@ -361,7 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 group.AbsolutePosition = attachPos; 361 group.AbsolutePosition = attachPos;
362 362
363 if (sp.PresenceType != PresenceType.Npc) 363 if (sp.PresenceType != PresenceType.Npc)
364 UpdateUserInventoryWithAttachment(sp, group, attachmentPt); 364 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
365 365
366 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 366 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
367 } 367 }
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
369 return true; 369 return true;
370 } 370 }
371 371
372 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) 372 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp)
373 { 373 {
374 // Remove any previous attachments 374 // Remove any previous attachments
375 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 375 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
@@ -379,18 +379,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
379 { 379 {
380 if (attachments[0].FromItemID != UUID.Zero) 380 if (attachments[0].FromItemID != UUID.Zero)
381 DetachSingleAttachmentToInvInternal(sp, attachments[0]); 381 DetachSingleAttachmentToInvInternal(sp, attachments[0]);
382 else 382 // Error logging commented because UUID.Zero now means temp attachment
383 m_log.WarnFormat( 383// else
384 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", 384// m_log.WarnFormat(
385 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); 385// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
386// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
386 } 387 }
387 388
388 // Add the new attachment to inventory if we don't already have it. 389 // Add the new attachment to inventory if we don't already have it.
389 UUID newAttachmentItemID = group.FromItemID; 390 if (!temp)
390 if (newAttachmentItemID == UUID.Zero) 391 {
391 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; 392 UUID newAttachmentItemID = group.FromItemID;
393 if (newAttachmentItemID == UUID.Zero)
394 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
392 395
393 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 396 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
397 }
394 } 398 }
395 399
396 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 400 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
@@ -474,6 +478,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
474 478
475 UUID inventoryID = so.FromItemID; 479 UUID inventoryID = so.FromItemID;
476 480
481 // As per Linden spec, drop is disabled for temp attachs
482 if (inventoryID == UUID.Zero)
483 return;
484
477// m_log.DebugFormat( 485// m_log.DebugFormat(
478// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", 486// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
479// so.Name, so.LocalId, inventoryID); 487// so.Name, so.LocalId, inventoryID);
@@ -484,7 +492,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
484 so.PrimCount, sp.UUID, sp.AbsolutePosition)) 492 so.PrimCount, sp.UUID, sp.AbsolutePosition))
485 return; 493 return;
486 494
487 bool changed = sp.Appearance.DetachAttachment(inventoryID); 495 bool changed = false;
496 if (inventoryID != UUID.Zero)
497 changed = sp.Appearance.DetachAttachment(inventoryID);
488 if (changed && m_scene.AvatarFactory != null) 498 if (changed && m_scene.AvatarFactory != null)
489 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 499 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
490 500
@@ -516,6 +526,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
516 526
517 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 527 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
518 { 528 {
529 // As per Linden spec, detach (take) is disabled for temp attachs
530 if (so.FromItemID == UUID.Zero)
531 return;
532
519 lock (sp.AttachmentsSyncLock) 533 lock (sp.AttachmentsSyncLock)
520 { 534 {
521 // Save avatar attachment information 535 // Save avatar attachment information
@@ -589,6 +603,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
589 /// <param name="saveAllScripted"></param> 603 /// <param name="saveAllScripted"></param>
590 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) 604 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState)
591 { 605 {
606 if (grp.FromItemID == UUID.Zero)
607 {
608 // We can't save temp attachments
609 grp.HasGroupChanged = false;
610 return;
611 }
612
592 // Saving attachments for NPCs messes them up for the real owner! 613 // Saving attachments for NPCs messes them up for the real owner!
593 INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); 614 INPCModule module = m_scene.RequestModuleInterface<INPCModule>();
594 if (module != null) 615 if (module != null)
@@ -845,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
845 // This will throw if the attachment fails 866 // This will throw if the attachment fails
846 try 867 try
847 { 868 {
848 AttachObject(sp, objatt, attachmentPt, false, false); 869 AttachObject(sp, objatt, attachmentPt, false, false, false);
849 } 870 }
850 catch (Exception e) 871 catch (Exception e)
851 { 872 {
@@ -1005,7 +1026,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1005 AttachmentPt &= 0x7f; 1026 AttachmentPt &= 0x7f;
1006 1027
1007 // Calls attach with a Zero position 1028 // Calls attach with a Zero position
1008 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true)) 1029 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false))
1009 { 1030 {
1010// m_log.Debug( 1031// m_log.Debug(
1011// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 1032// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 273e290..d9a619d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -189,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
189 189
190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
191 191
192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
193 193
194 // Check status on scene presence 194 // Check status on scene presence
195 Assert.That(sp.HasAttachments(), Is.True); 195 Assert.That(sp.HasAttachments(), Is.True);
@@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
243 sp2.AbsolutePosition = new Vector3(0, 0, 0); 243 sp2.AbsolutePosition = new Vector3(0, 0, 0);
244 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 244 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
245 245
246 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 246 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
247 247
248 Assert.That(sp.HasAttachments(), Is.False); 248 Assert.That(sp.HasAttachments(), Is.False);
249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 89cc4f6..bd7bd82 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -66,11 +66,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
66 scene.RegisterModuleInterface<IAvatarFactoryModule>(this); 66 scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
67 scene.EventManager.OnNewClient += SubscribeToClientEvents; 67 scene.EventManager.OnNewClient += SubscribeToClientEvents;
68 68
69 IConfig sconfig = config.Configs["Startup"]; 69 IConfig appearanceConfig = config.Configs["Appearance"];
70 if (sconfig != null) 70 if (appearanceConfig != null)
71 { 71 {
72 m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 72 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
73 m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 73 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
74 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 74 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
75 } 75 }
76 76
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index ae4d52a..8b2f2f8 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -596,9 +596,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
596 } 596 }
597 break; 597 break;
598 case "R": 598 case "R":
599 Font anewFont = new Font(myFont, FontStyle.Regular); 599 // We need to place this newFont inside its own context so that the .NET compiler
600 myFont.Dispose(); 600 // doesn't complain about a redefinition of an existing newFont, even though there is none
601 myFont = anewFont; 601 // The mono compiler doesn't produce this error.
602 {
603 Font newFont = new Font(myFont, FontStyle.Regular);
604 myFont.Dispose();
605 myFont = newFont;
606 }
602 break; 607 break;
603 } 608 }
604 } 609 }
@@ -768,4 +773,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
768 return null; 773 return null;
769 } 774 }
770 } 775 }
771} \ No newline at end of file 776}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
index c179a34..0780d86 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
124 LandData landData = lo.LandData; 124 LandData landData = lo.LandData;
125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, 125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
126 landData.GlobalID.ToString()); 126 landData.GlobalID.ToString());
127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData)); 127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
128 } 128 }
129 129
130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); 130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 11a13e1..90a13a7 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
84 /// <param name="AttachmentPt"></param> 84 /// <param name="AttachmentPt"></param>
85 /// <param name="silent"></param> 85 /// <param name="silent"></param>
86 /// <returns>true if the object was successfully attached, false otherwise</returns> 86 /// <returns>true if the object was successfully attached, false otherwise</returns>
87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo); 87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp);
88 88
89 /// <summary> 89 /// <summary>
90 /// Rez an attachment from user inventory and change inventory status to match. 90 /// Rez an attachment from user inventory and change inventory status to match.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 3db7c7d..1fc4c52 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -842,7 +842,6 @@ namespace OpenSim.Region.Framework.Scenes
842 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 842 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
843 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 843 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
844 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 844 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
845 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
846 } 845 }
847 } 846 }
848 catch (Exception e) 847 catch (Exception e)
@@ -850,6 +849,14 @@ namespace OpenSim.Region.Framework.Scenes
850 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString()); 849 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
851 } 850 }
852 851
852 // FIXME: Ultimately this should be in a module.
853 IConfig appearanceConfig = m_config.Configs["Appearance"];
854 if (appearanceConfig != null)
855 {
856 SendPeriodicAppearanceUpdates
857 = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates);
858 }
859
853 #endregion Region Config 860 #endregion Region Config
854 861
855 #region Interest Management 862 #region Interest Management
@@ -2748,7 +2755,7 @@ namespace OpenSim.Region.Framework.Scenes
2748 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2755 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2749 2756
2750 if (AttachmentsModule != null) 2757 if (AttachmentsModule != null)
2751 AttachmentsModule.AttachObject(sp, grp, 0, false, false); 2758 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false);
2752 } 2759 }
2753 else 2760 else
2754 { 2761 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d51281d..d837adb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -951,7 +951,7 @@ namespace OpenSim.Region.Framework.Scenes
951 /// its existing localID and UUID. 951 /// its existing localID and UUID.
952 /// </summary> 952 /// </summary>
953 /// <param name='part'>Root part for this scene object.</param> 953 /// <param name='part'>Root part for this scene object.</param>
954 public SceneObjectGroup(SceneObjectPart part) 954 public SceneObjectGroup(SceneObjectPart part) : this()
955 { 955 {
956 SetRootPart(part); 956 SetRootPart(part);
957 } 957 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
new file mode 100644
index 0000000..b166588
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -0,0 +1,126 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Console;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.Attachments
45{
46 /// <summary>
47 /// A module that just holds commands for inspecting avatar appearance.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")]
50 public class TempAttachmentsModule : INonSharedRegionModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Scene m_scene;
55
56 public void Initialise(IConfigSource configSource)
57 {
58 }
59
60 public void AddRegion(Scene scene)
61 {
62 m_scene = scene;
63
64 IScriptModuleComms comms = scene.RequestModuleInterface<IScriptModuleComms>();
65 if (comms != null)
66 {
67 comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp");
68 m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions");
69 }
70 else
71 {
72 m_log.ErrorFormat("[TEMP ATTACHS]: Failed to register script functions");
73 }
74 }
75
76 public void RemoveRegion(Scene scene)
77 {
78 }
79
80 public void RegionLoaded(Scene scene)
81 {
82 }
83
84 public void Close()
85 {
86 }
87
88 public Type ReplaceableInterface
89 {
90 get { return null; }
91 }
92
93 public string Name
94 {
95 get { return "TempAttachmentsModule"; }
96 }
97
98 private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
99 {
100 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
101
102 if (hostPart == null)
103 return;
104
105 if (hostPart.ParentGroup.IsAttachment)
106 return;
107
108 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
109 if (attachmentsModule == null)
110 return;
111
112 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
113 if (item == null)
114 return;
115
116 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
117 return;
118
119 ScenePresence target;
120 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
121 return;
122
123 attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true);
124 }
125 }
126}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
new file mode 100755
index 0000000..72df6b9
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -0,0 +1,80 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public class BS6DofConstraint : BSConstraint
36{
37 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot,
40 Vector3 frame2, Quaternion frame2rot )
41 {
42 m_world = world;
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_constraint = new BulletConstraint(
46 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 frame1, frame1rot,
48 frame2, frame2rot,
49 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
50 m_enabled = true;
51 }
52
53 public bool SetCFMAndERP(float cfm, float erp)
54 {
55 bool ret = true;
56 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
57 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
58 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
59 return ret;
60 }
61
62 public bool UseFrameOffset(bool useOffset)
63 {
64 bool ret = false;
65 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
66 if (m_enabled)
67 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
68 return ret;
69 }
70
71 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
72 {
73 bool ret = false;
74 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
75 if (m_enabled)
76 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
77 return ret;
78 }
79}
80}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 09e1f0c..f164afe 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -40,6 +40,7 @@ public class BSCharacter : PhysicsActor
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 public BSScene Scene { get { return _scene; } }
43 private String _avName; 44 private String _avName;
44 // private bool _stopped; 45 // private bool _stopped;
45 private Vector3 _size; 46 private Vector3 _size;
@@ -73,6 +74,12 @@ public class BSCharacter : PhysicsActor
73 private bool _kinematic; 74 private bool _kinematic;
74 private float _buoyancy; 75 private float _buoyancy;
75 76
77 private BulletBody m_body;
78 public BulletBody Body {
79 get { return m_body; }
80 set { m_body = value; }
81 }
82
76 private int _subscribedEventsMs = 0; 83 private int _subscribedEventsMs = 0;
77 private int _nextCollisionOkTime = 0; 84 private int _nextCollisionOkTime = 0;
78 85
@@ -95,7 +102,9 @@ public class BSCharacter : PhysicsActor
95 _orientation = Quaternion.Identity; 102 _orientation = Quaternion.Identity;
96 _velocity = Vector3.Zero; 103 _velocity = Vector3.Zero;
97 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 104 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
98 _scale = new Vector3(1f, 1f, 1f); 105 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
99 _density = _scene.Params.avatarDensity; 108 _density = _scene.Params.avatarDensity;
100 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
101 110
@@ -113,9 +122,13 @@ public class BSCharacter : PhysicsActor
113 shapeData.Restitution = _scene.Params.avatarRestitution; 122 shapeData.Restitution = _scene.Params.avatarRestitution;
114 123
115 // do actual create at taint time 124 // do actual create at taint time
116 _scene.TaintedObject(delegate() 125 _scene.TaintedObject("BSCharacter.create", delegate()
117 { 126 {
118 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
128
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
119 }); 132 });
120 133
121 return; 134 return;
@@ -124,7 +137,8 @@ public class BSCharacter : PhysicsActor
124 // called when this character is being destroyed and the resources should be released 137 // called when this character is being destroyed and the resources should be released
125 public void Destroy() 138 public void Destroy()
126 { 139 {
127 _scene.TaintedObject(delegate() 140 // DetailLog("{0},Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate()
128 { 142 {
129 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
130 }); 144 });
@@ -138,9 +152,28 @@ public class BSCharacter : PhysicsActor
138 public override bool Stopped { 152 public override bool Stopped {
139 get { return false; } 153 get { return false; }
140 } 154 }
141 public override Vector3 Size { 155 public override Vector3 Size {
142 get { return _size; } 156 get
143 set { _size = value; 157 {
158 // Avatar capsule size is kept in the scale parameter.
159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
160 }
161
162 set {
163 // When an avatar's size is set, only the height is changed
164 // and that really only depends on the radius.
165 _size = value;
166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
167
168 // TODO: something has to be done with the avatar's vertical position
169
170 ComputeAvatarVolumeAndMass();
171
172 _scene.TaintedObject("BSCharacter.setSize", delegate()
173 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
175 });
176
144 } 177 }
145 } 178 }
146 public override PrimitiveBaseShape Shape { 179 public override PrimitiveBaseShape Shape {
@@ -172,12 +205,37 @@ public class BSCharacter : PhysicsActor
172 } 205 }
173 set { 206 set {
174 _position = value; 207 _position = value;
175 _scene.TaintedObject(delegate() 208 PositionSanityCheck();
209
210 _scene.TaintedObject("BSCharacter.setPosition", delegate()
176 { 211 {
212 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
177 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
178 }); 214 });
179 } 215 }
180 } 216 }
217
218 // Check that the current position is sane and, if not, modify the position to make it so.
219 // Check for being below terrain and being out of bounds.
220 // Returns 'true' of the position was made sane by some action.
221 private bool PositionSanityCheck()
222 {
223 bool ret = false;
224
225 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight)
228 {
229 DetailLog("{0},PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
230 _position.Z = terrainHeight + 2.0f;
231 ret = true;
232 }
233
234 // TODO: check for out of bounds
235
236 return ret;
237 }
238
181 public override float Mass { 239 public override float Mass {
182 get { 240 get {
183 return _mass; 241 return _mass;
@@ -188,9 +246,10 @@ public class BSCharacter : PhysicsActor
188 set { 246 set {
189 _force = value; 247 _force = value;
190 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
191 _scene.TaintedObject(delegate() 249 Scene.TaintedObject("BSCharacter.SetForce", delegate()
192 { 250 {
193 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
194 }); 253 });
195 } 254 }
196 } 255 }
@@ -214,8 +273,9 @@ public class BSCharacter : PhysicsActor
214 set { 273 set {
215 _velocity = value; 274 _velocity = value;
216 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
217 _scene.TaintedObject(delegate() 276 _scene.TaintedObject("BSCharacter.setVelocity", delegate()
218 { 277 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
219 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
220 }); 280 });
221 } 281 }
@@ -239,7 +299,7 @@ public class BSCharacter : PhysicsActor
239 set { 299 set {
240 _orientation = value; 300 _orientation = value;
241 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
242 _scene.TaintedObject(delegate() 302 _scene.TaintedObject("BSCharacter.setOrientation", delegate()
243 { 303 {
244 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
245 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
@@ -259,9 +319,12 @@ public class BSCharacter : PhysicsActor
259 public override bool Flying { 319 public override bool Flying {
260 get { return _flying; } 320 get { return _flying; }
261 set { 321 set {
262 _flying = value; 322 if (_flying != value)
263 // simulate flying by changing the effect of gravity 323 {
264 this.Buoyancy = ComputeBuoyancyFromFlying(_flying); 324 _flying = value;
325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
265 } 328 }
266 } 329 }
267 private float ComputeBuoyancyFromFlying(bool ifFlying) { 330 private float ComputeBuoyancyFromFlying(bool ifFlying) {
@@ -303,8 +366,9 @@ public class BSCharacter : PhysicsActor
303 public override float Buoyancy { 366 public override float Buoyancy {
304 get { return _buoyancy; } 367 get { return _buoyancy; }
305 set { _buoyancy = value; 368 set { _buoyancy = value;
306 _scene.TaintedObject(delegate() 369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
307 { 370 {
371 DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
308 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
309 }); 373 });
310 } 374 }
@@ -349,9 +413,10 @@ public class BSCharacter : PhysicsActor
349 _force.Y += force.Y; 413 _force.Y += force.Y;
350 _force.Z += force.Z; 414 _force.Z += force.Z;
351 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
352 _scene.TaintedObject(delegate() 416 _scene.TaintedObject("BSCharacter.AddForce", delegate()
353 { 417 {
354 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 418 DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
355 }); 420 });
356 } 421 }
357 else 422 else
@@ -369,11 +434,25 @@ public class BSCharacter : PhysicsActor
369 // Turn on collision events at a rate no faster than one every the given milliseconds 434 // Turn on collision events at a rate no faster than one every the given milliseconds
370 public override void SubscribeEvents(int ms) { 435 public override void SubscribeEvents(int ms) {
371 _subscribedEventsMs = ms; 436 _subscribedEventsMs = ms;
372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 437 if (ms > 0)
438 {
439 // make sure first collision happens
440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
441
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
443 {
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 });
446 }
373 } 447 }
374 // Stop collision events 448 // Stop collision events
375 public override void UnSubscribeEvents() { 449 public override void UnSubscribeEvents() {
376 _subscribedEventsMs = 0; 450 _subscribedEventsMs = 0;
451 // Avatars get all their collision events
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
453 // {
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
455 // });
377 } 456 }
378 // Return 'true' if someone has subscribed to events 457 // Return 'true' if someone has subscribed to events
379 public override bool SubscribedEvents() { 458 public override bool SubscribedEvents() {
@@ -385,9 +464,15 @@ public class BSCharacter : PhysicsActor
385 { 464 {
386 _avatarVolume = (float)( 465 _avatarVolume = (float)(
387 Math.PI 466 Math.PI
388 * _scene.Params.avatarCapsuleRadius * _scale.X 467 * _scale.X
389 * _scene.Params.avatarCapsuleRadius * _scale.Y 468 * _scale.Y // the area of capsule cylinder
390 * _scene.Params.avatarCapsuleHeight * _scale.Z); 469 * _scale.Z // times height of capsule cylinder
470 + 1.33333333f
471 * Math.PI
472 * _scale.X
473 * Math.Min(_scale.X, _scale.Y)
474 * _scale.Y // plus the volume of the capsule end caps
475 );
391 _mass = _density * _avatarVolume; 476 _mass = _density * _avatarVolume;
392 } 477 }
393 478
@@ -395,43 +480,17 @@ public class BSCharacter : PhysicsActor
395 // the world that things have changed. 480 // the world that things have changed.
396 public void UpdateProperties(EntityProperties entprop) 481 public void UpdateProperties(EntityProperties entprop)
397 { 482 {
398 /*
399 bool changed = false;
400 // we assign to the local variables so the normal set action does not happen
401 if (_position != entprop.Position) {
402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
418 _rotationalVelocity = entprop.RotationalVelocity;
419 changed = true;
420 }
421 if (changed) {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is code in the heartbeat
424 // loop that updates avatars.
425 // base.RequestPhysicsterseUpdate();
426 }
427 */
428 _position = entprop.Position; 483 _position = entprop.Position;
429 _orientation = entprop.Rotation; 484 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity; 485 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration; 486 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity; 487 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop. 488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
434 // base.RequestPhysicsterseUpdate(); 489 // base.RequestPhysicsterseUpdate();
490
491 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
492 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
493 entprop.Acceleration, entprop.RotationalVelocity);
435 } 494 }
436 495
437 // Called by the scene when a collision with this object is reported 496 // Called by the scene when a collision with this object is reported
@@ -480,5 +539,10 @@ public class BSCharacter : PhysicsActor
480 // End kludge 539 // End kludge
481 } 540 }
482 541
542 // Invoke the detailed logger and output something if it's enabled.
543 private void DetailLog(string msg, params Object[] args)
544 {
545 Scene.PhysicsLogging.Write(msg, args);
546 }
483} 547}
484} 548}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index ea3093a..da26b72 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -32,35 +32,26 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public class BSConstraint : IDisposable 35public abstract class BSConstraint : IDisposable
36{ 36{
37 private BulletSim m_world; 37 protected BulletSim m_world;
38 private BulletBody m_body1; 38 protected BulletBody m_body1;
39 private BulletBody m_body2; 39 protected BulletBody m_body2;
40 private BulletConstraint m_constraint; 40 protected BulletConstraint m_constraint;
41 private bool m_enabled = false; 41 protected bool m_enabled = false;
42 42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 43 public BSConstraint()
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 { 44 {
48 m_world = world;
49 m_body1 = obj1;
50 m_body2 = obj2;
51 m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot,
53 frame2, frame2rot,
54 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
55 m_enabled = true;
56 } 45 }
57 46
58 public void Dispose() 47 public virtual void Dispose()
59 { 48 {
60 if (m_enabled) 49 if (m_enabled)
61 { 50 {
62 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); 51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
63 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); 52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero;
64 m_enabled = false; 55 m_enabled = false;
65 } 56 }
66 } 57 }
@@ -68,7 +59,7 @@ public class BSConstraint : IDisposable
68 public BulletBody Body1 { get { return m_body1; } } 59 public BulletBody Body1 { get { return m_body1; } }
69 public BulletBody Body2 { get { return m_body2; } } 60 public BulletBody Body2 { get { return m_body2; } }
70 61
71 public bool SetLinearLimits(Vector3 low, Vector3 high) 62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
72 { 63 {
73 bool ret = false; 64 bool ret = false;
74 if (m_enabled) 65 if (m_enabled)
@@ -76,7 +67,7 @@ public class BSConstraint : IDisposable
76 return ret; 67 return ret;
77 } 68 }
78 69
79 public bool SetAngularLimits(Vector3 low, Vector3 high) 70 public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
80 { 71 {
81 bool ret = false; 72 bool ret = false;
82 if (m_enabled) 73 if (m_enabled)
@@ -84,34 +75,7 @@ public class BSConstraint : IDisposable
84 return ret; 75 return ret;
85 } 76 }
86 77
87 public bool SetCFMAndERP(float cfm, float erp) 78 public virtual bool CalculateTransforms()
88 {
89 bool ret = true;
90 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
91 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
92 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
93 return ret;
94 }
95
96 public bool UseFrameOffset(bool useOffset)
97 {
98 bool ret = false;
99 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
100 if (m_enabled)
101 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
102 return ret;
103 }
104
105 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
106 {
107 bool ret = false;
108 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
109 if (m_enabled)
110 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
111 return ret;
112 }
113
114 public bool CalculateTransforms()
115 { 79 {
116 bool ret = false; 80 bool ret = false;
117 if (m_enabled) 81 if (m_enabled)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index c88e645..3df2ddc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -63,21 +63,13 @@ public class BSConstraintCollection : IDisposable
63 m_constraints.Clear(); 63 m_constraints.Clear();
64 } 64 }
65 65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 }
75
76 public bool AddConstraint(BSConstraint cons) 66 public bool AddConstraint(BSConstraint cons)
77 { 67 {
78 // There is only one constraint between any bodies. Remove any old just to make sure. 68 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 69 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80 70
71 m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID);
72
81 m_constraints.Add(cons); 73 m_constraints.Add(cons);
82 74
83 return true; 75 return true;
@@ -118,6 +110,7 @@ public class BSConstraintCollection : IDisposable
118 110
119 if (this.TryGetConstraint(body1, body2, out constrain)) 111 if (this.TryGetConstraint(body1, body2, out constrain))
120 { 112 {
113 m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID);
121 // remove the constraint from our collection 114 // remove the constraint from our collection
122 m_constraints.Remove(constrain); 115 m_constraints.Remove(constrain);
123 // tell the engine that all its structures need to be freed 116 // tell the engine that all its structures need to be freed
@@ -158,10 +151,11 @@ public class BSConstraintCollection : IDisposable
158 151
159 public bool RecalculateAllConstraints() 152 public bool RecalculateAllConstraints()
160 { 153 {
161 foreach (BSConstraint constrain in m_constraints) 154 ForEachConstraint(delegate(BSConstraint constrain)
162 { 155 {
163 constrain.CalculateTransforms(); 156 constrain.CalculateTransforms();
164 } 157 return false;
158 });
165 return true; 159 return true;
166 } 160 }
167 161
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 6f8430c..4a71612 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -40,6 +40,7 @@ public class BSLinkset
40 public BSPrim Root { get { return m_linksetRoot; } } 40 public BSPrim Root { get { return m_linksetRoot; } }
41 41
42 private BSScene m_scene; 42 private BSScene m_scene;
43 public BSScene Scene { get { return m_scene; } }
43 44
44 private List<BSPrim> m_children; 45 private List<BSPrim> m_children;
45 46
@@ -80,14 +81,14 @@ public class BSLinkset
80 81
81 // Link to a linkset where the child knows the parent. 82 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking. 83 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership. 84 // We return the parent's linkset so the child can track its membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) 85 public BSLinkset AddMeToLinkset(BSPrim child)
85 { 86 {
86 lock (m_linksetActivityLock) 87 lock (m_linksetActivityLock)
87 { 88 {
88 parent.Linkset.AddChildToLinkset(child); 89 AddChildToLinkset(child);
89 } 90 }
90 return parent.Linkset; 91 return this;
91 } 92 }
92 93
93 public BSLinkset RemoveMeFromLinkset(BSPrim child) 94 public BSLinkset RemoveMeFromLinkset(BSPrim child)
@@ -101,7 +102,7 @@ public class BSLinkset
101 { 102 {
102 // Note that we don't do a foreach because the remove routine 103 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list. 104 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]); 105 RemoveChildFromOtherLinkset(m_children[0]);
105 } 106 }
106 m_children.Clear(); // just to make sure 107 m_children.Clear(); // just to make sure
107 } 108 }
@@ -113,9 +114,10 @@ public class BSLinkset
113 } 114 }
114 115
115 // The child is down to a linkset of just itself 116 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child); 117 return new BSLinkset(Scene, child);
117 } 118 }
118 119
120 /* DEPRECATED: this is really bad in that it trys to unlink other prims.
119 // An existing linkset had one of its members rebuilt or something. 121 // An existing linkset had one of its members rebuilt or something.
120 // Go through the linkset and rebuild the pointers to the bodies of the linkset members. 122 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
121 public BSLinkset RefreshLinkset(BSPrim requestor) 123 public BSLinkset RefreshLinkset(BSPrim requestor)
@@ -124,6 +126,7 @@ public class BSLinkset
124 126
125 lock (m_linksetActivityLock) 127 lock (m_linksetActivityLock)
126 { 128 {
129 // The body pointer is refetched in case anything has moved.
127 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); 130 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
128 if (aPtr == System.IntPtr.Zero) 131 if (aPtr == System.IntPtr.Zero)
129 { 132 {
@@ -155,13 +158,14 @@ public class BSLinkset
155 } 158 }
156 foreach (BSPrim bsp in toRemove) 159 foreach (BSPrim bsp in toRemove)
157 { 160 {
158 RemoveChildFromLinkset(bsp); 161 RemoveChildFromOtherLinkset(bsp);
159 } 162 }
160 } 163 }
161 } 164 }
162 165
163 return ret; 166 return ret;
164 } 167 }
168 */
165 169
166 170
167 // Return 'true' if the passed object is the root object of this linkset 171 // Return 'true' if the passed object is the root object of this linkset
@@ -170,6 +174,8 @@ public class BSLinkset
170 return (requestor.LocalID == m_linksetRoot.LocalID); 174 return (requestor.LocalID == m_linksetRoot.LocalID);
171 } 175 }
172 176
177 public int NumberOfChildren { get { return m_children.Count; } }
178
173 // Return 'true' if this linkset has any children (more than the root member) 179 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 180 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 181
@@ -208,7 +214,8 @@ public class BSLinkset
208 com += bp.Position * bp.MassRaw; 214 com += bp.Position * bp.MassRaw;
209 totalMass += bp.MassRaw; 215 totalMass += bp.MassRaw;
210 } 216 }
211 com /= totalMass; 217 if (totalMass != 0f)
218 com /= totalMass;
212 219
213 return com; 220 return com;
214 } 221 }
@@ -221,51 +228,54 @@ public class BSLinkset
221 { 228 {
222 com += bp.Position * bp.MassRaw; 229 com += bp.Position * bp.MassRaw;
223 } 230 }
224 com /= m_children.Count + 1; 231 com /= (m_children.Count + 1);
225 232
226 return com; 233 return com;
227 } 234 }
228 235
229 // I am the root of a linkset and a new child is being added 236 // I am the root of a linkset and a new child is being added
230 public void AddChildToLinkset(BSPrim pchild) 237 // Called while LinkActivity is locked.
238 public void AddChildToLinkset(BSPrim child)
231 { 239 {
232 BSPrim child = pchild;
233 if (!HasChild(child)) 240 if (!HasChild(child))
234 { 241 {
235 m_children.Add(child); 242 m_children.Add(child);
236 243
237 m_scene.TaintedObject(delegate() 244 BSPrim root = Root; // capture the root as of now
245 m_scene.TaintedObject("AddChildToLinkset", delegate()
238 { 246 {
239 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 247 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
240 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 248 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child 249 PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child
242 }); 250 });
243 } 251 }
244 return; 252 return;
245 } 253 }
246 254
255 // Forcefully removing a child from a linkset.
256 // This is not being called by the child so we have to make sure the child doesn't think
257 // it's still connected to the linkset.
258 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
259 // has to be updated also (like pointer to prim's parent).
260 public void RemoveChildFromOtherLinkset(BSPrim pchild)
261 {
262 pchild.Linkset = new BSLinkset(m_scene, pchild);
263 RemoveChildFromLinkset(pchild);
264 }
265
247 // I am the root of a linkset and one of my children is being removed. 266 // I am the root of a linkset and one of my children is being removed.
248 // Safe to call even if the child is not really in my linkset. 267 // Safe to call even if the child is not really in my linkset.
249 public void RemoveChildFromLinkset(BSPrim pchild) 268 public void RemoveChildFromLinkset(BSPrim child)
250 { 269 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child)) 270 if (m_children.Remove(child))
254 { 271 {
255 m_scene.TaintedObject(delegate() 272 BSPrim root = Root; // capture the root as of now
273 m_scene.TaintedObject("RemoveChildFromLinkset", delegate()
256 { 274 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 275 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 276 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
259 277
260 if (m_children.Count == 0) 278 PhysicallyUnlinkAChildFromRoot(root, child);
261 {
262 // if the linkset is empty, make sure all linkages have been removed
263 PhysicallyUnlinkAllChildrenFromRoot();
264 }
265 else
266 {
267 PhysicallyUnlinkAChildFromRoot(pchild);
268 }
269 }); 279 });
270 } 280 }
271 else 281 else
@@ -278,14 +288,14 @@ public class BSLinkset
278 288
279 // Create a constraint between me (root of linkset) and the passed prim (the child). 289 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time! 290 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim) 291 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
282 { 292 {
283 // Zero motion for children so they don't interpolate 293 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion(); 294 childPrim.ZeroMotion();
285 295
286 // relative position normalized to the root prim 296 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); 297 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; 298 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
289 299
290 // relative rotation of the child to the parent 300 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 301 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
@@ -293,16 +303,17 @@ public class BSLinkset
293 // create a constraint that allows no freedom of movement between the two objects 303 // create a constraint that allows no freedom of movement between the two objects
294 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 304 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
295 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); 305 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
296 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 306 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint( 307 BS6DofConstraint constrain = new BS6DofConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body, 308 m_scene.World, rootPrim.Body, childPrim.Body,
299 // childRelativePosition, 309 childRelativePosition,
300 // childRelativeRotation, 310 childRelativeRotation,
301 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity,
303 OMV.Vector3.Zero, 311 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity 312 -childRelativeRotation
305 ); 313 );
314 m_scene.Constraints.AddConstraint(constrain);
315
316 // zero linear and angular limits makes the objects unable to move in relation to each other
306 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 317 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 318 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308 319
@@ -317,29 +328,32 @@ public class BSLinkset
317 328
318 // Remove linkage between myself and a particular child 329 // Remove linkage between myself and a particular child
319 // Called at taint time! 330 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) 331 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
321 { 332 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", 333 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); 334 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 335 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 336
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); 337 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
338 // Make the child refresh its location
339 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
327 } 340 }
328 341
329 // Remove linkage between myself and any possible children I might have 342 // Remove linkage between myself and any possible children I might have
330 // Called at taint time! 343 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot() 344 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
332 { 345 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 346 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); 347 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); 348
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 349 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
337 } 350 }
338 351
339 // Invoke the detailed logger and output something if it's enabled. 352 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args) 353 private void DebugLog(string msg, params Object[] args)
341 { 354 {
342 m_scene.Logger.DebugFormat(msg, args); 355 if (m_scene.ShouldDebugLog)
356 m_scene.Logger.DebugFormat(msg, args);
343 } 357 }
344 358
345 // Invoke the detailed logger and output something if it's enabled. 359 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ebfd85b..05cc822 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,7 +42,7 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); } 45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
46 46
47 private IMesh _mesh; 47 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
@@ -138,14 +138,15 @@ public sealed class BSPrim : PhysicsActor
138 _isPhysical = pisPhysical; 138 _isPhysical = pisPhysical;
139 _isVolumeDetect = false; 139 _isVolumeDetect = false;
140 _subscribedEventsMs = 0; 140 _subscribedEventsMs = 0;
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 143 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 145 _vehicle = new BSDynamics(this); // add vehicleness
146 _mass = CalculateMass(); 146 _mass = CalculateMass();
147 // do the actual object creation at taint time 147 // do the actual object creation at taint time
148 _scene.TaintedObject(delegate() 148 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate()
149 { 150 {
150 RecreateGeomAndObject(); 151 RecreateGeomAndObject();
151 152
@@ -160,17 +161,22 @@ public sealed class BSPrim : PhysicsActor
160 public void Destroy() 161 public void Destroy()
161 { 162 {
162 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
163 // DetailLog("{0},Destroy", LocalID); 164
165 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.Root;
167 int childrenBefore = _linkset.NumberOfChildren;
168
169 _linkset = _linkset.RemoveMeFromLinkset(this);
170
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren);
164 173
165 // Undo any vehicle properties 174 // Undo any vehicle properties
166 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 175 this.VehicleType = (int)Vehicle.TYPE_NONE;
167 _scene.RemoveVehiclePrim(this); // just to make sure
168 176
169 _scene.TaintedObject(delegate() 177 _scene.TaintedObject("BSPrim.destroy", delegate()
170 { 178 {
171 // Undo any links between me and any other object 179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
172 _linkset = _linkset.RemoveMeFromLinkset(this);
173
174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
176 }); 182 });
@@ -183,11 +189,11 @@ public sealed class BSPrim : PhysicsActor
183 get { return _size; } 189 get { return _size; }
184 set { 190 set {
185 _size = value; 191 _size = value;
186 _scene.TaintedObject(delegate() 192 _scene.TaintedObject("BSPrim.setSize", delegate()
187 { 193 {
188 _mass = CalculateMass(); // changing size changes the mass 194 _mass = CalculateMass(); // changing size changes the mass
189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
190 DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
191 RecreateGeomAndObject(); 197 RecreateGeomAndObject();
192 }); 198 });
193 } 199 }
@@ -195,7 +201,7 @@ public sealed class BSPrim : PhysicsActor
195 public override PrimitiveBaseShape Shape { 201 public override PrimitiveBaseShape Shape {
196 set { 202 set {
197 _pbs = value; 203 _pbs = value;
198 _scene.TaintedObject(delegate() 204 _scene.TaintedObject("BSPrim.setShape", delegate()
199 { 205 {
200 _mass = CalculateMass(); // changing the shape changes the mass 206 _mass = CalculateMass(); // changing the shape changes the mass
201 RecreateGeomAndObject(); 207 RecreateGeomAndObject();
@@ -213,7 +219,7 @@ public sealed class BSPrim : PhysicsActor
213 public override bool Selected { 219 public override bool Selected {
214 set { 220 set {
215 _isSelected = value; 221 _isSelected = value;
216 _scene.TaintedObject(delegate() 222 _scene.TaintedObject("BSPrim.setSelected", delegate()
217 { 223 {
218 SetObjectDynamic(); 224 SetObjectDynamic();
219 }); 225 });
@@ -224,10 +230,17 @@ public sealed class BSPrim : PhysicsActor
224 // link me to the specified parent 230 // link me to the specified parent
225 public override void link(PhysicsActor obj) { 231 public override void link(PhysicsActor obj) {
226 BSPrim parent = obj as BSPrim; 232 BSPrim parent = obj as BSPrim;
227 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 233 if (parent != null)
228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); 234 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
236 BSPrim parentBefore = _linkset.Root;
237 int childrenBefore = _linkset.NumberOfChildren;
238
239 _linkset = parent.Linkset.AddMeToLinkset(this);
229 240
230 _linkset = _linkset.AddMeToLinkset(this, parent); 241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren);
243 }
231 return; 244 return;
232 } 245 }
233 246
@@ -237,9 +250,14 @@ public sealed class BSPrim : PhysicsActor
237 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
238 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
239 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); 252 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
241 253
242 _linkset.RemoveMeFromLinkset(this); 254 BSPrim parentBefore = _linkset.Root;
255 int childrenBefore = _linkset.NumberOfChildren;
256
257 _linkset = _linkset.RemoveMeFromLinkset(this);
258
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren);
243 return; 261 return;
244 } 262 }
245 263
@@ -262,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
262 280
263 public override void LockAngularMotion(OMV.Vector3 axis) 281 public override void LockAngularMotion(OMV.Vector3 axis)
264 { 282 {
265 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); 283 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
266 return; 284 return;
267 } 285 }
268 286
@@ -279,9 +297,9 @@ public sealed class BSPrim : PhysicsActor
279 set { 297 set {
280 _position = value; 298 _position = value;
281 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
282 _scene.TaintedObject(delegate() 300 _scene.TaintedObject("BSPrim.setPosition", delegate()
283 { 301 {
284 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 302 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
285 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
286 }); 304 });
287 } 305 }
@@ -316,9 +334,9 @@ public sealed class BSPrim : PhysicsActor
316 get { return _force; } 334 get { return _force; }
317 set { 335 set {
318 _force = value; 336 _force = value;
319 _scene.TaintedObject(delegate() 337 _scene.TaintedObject("BSPrim.setForce", delegate()
320 { 338 {
321 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); 339 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
322 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
323 BulletSimAPI.SetObjectForce2(Body.Ptr, _force); 341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
324 }); 342 });
@@ -331,53 +349,41 @@ public sealed class BSPrim : PhysicsActor
331 } 349 }
332 set { 350 set {
333 Vehicle type = (Vehicle)value; 351 Vehicle type = (Vehicle)value;
334 _scene.TaintedObject(delegate() 352 BSPrim vehiclePrim = this;
353 _scene.TaintedObject("setVehicleType", delegate()
335 { 354 {
336 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); 355 // Done at taint time so we're sure the physics engine is not using the variables
356 // Vehicle code changes the parameters for this vehicle type.
337 _vehicle.ProcessTypeChange(type); 357 _vehicle.ProcessTypeChange(type);
338 if (type == Vehicle.TYPE_NONE) 358 // Tell the scene about the vehicle so it will get processing each frame.
339 { 359 _scene.VehicleInSceneTypeChanged(this, type);
340 _scene.RemoveVehiclePrim(this);
341 }
342 else
343 {
344 _scene.TaintedObject(delegate()
345 {
346 // Tell the physics engine to clear state
347 BulletSimAPI.ClearForces2(this.Body.Ptr);
348 });
349
350 // make it so the scene will call us each tick to do vehicle things
351 _scene.AddVehiclePrim(this);
352 }
353 return;
354 }); 360 });
355 } 361 }
356 } 362 }
357 public override void VehicleFloatParam(int param, float value) 363 public override void VehicleFloatParam(int param, float value)
358 { 364 {
359 _scene.TaintedObject(delegate() 365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
360 { 366 {
361 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
362 }); 368 });
363 } 369 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 370 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 371 {
366 _scene.TaintedObject(delegate() 372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
367 { 373 {
368 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
369 }); 375 });
370 } 376 }
371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
372 { 378 {
373 _scene.TaintedObject(delegate() 379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
374 { 380 {
375 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
376 }); 382 });
377 } 383 }
378 public override void VehicleFlags(int param, bool remove) 384 public override void VehicleFlags(int param, bool remove)
379 { 385 {
380 _scene.TaintedObject(delegate() 386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate()
381 { 387 {
382 _vehicle.ProcessVehicleFlags(param, remove); 388 _vehicle.ProcessVehicleFlags(param, remove);
383 }); 389 });
@@ -395,7 +401,7 @@ public sealed class BSPrim : PhysicsActor
395 public override void SetVolumeDetect(int param) { 401 public override void SetVolumeDetect(int param) {
396 bool newValue = (param != 0); 402 bool newValue = (param != 0);
397 _isVolumeDetect = newValue; 403 _isVolumeDetect = newValue;
398 _scene.TaintedObject(delegate() 404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
399 { 405 {
400 SetObjectDynamic(); 406 SetObjectDynamic();
401 }); 407 });
@@ -406,9 +412,9 @@ public sealed class BSPrim : PhysicsActor
406 get { return _velocity; } 412 get { return _velocity; }
407 set { 413 set {
408 _velocity = value; 414 _velocity = value;
409 _scene.TaintedObject(delegate() 415 _scene.TaintedObject("BSPrim.setVelocity", delegate()
410 { 416 {
411 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); 417 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
412 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
413 }); 419 });
414 } 420 }
@@ -416,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
416 public override OMV.Vector3 Torque { 422 public override OMV.Vector3 Torque {
417 get { return _torque; } 423 get { return _torque; }
418 set { _torque = value; 424 set { _torque = value;
419 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); 425 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
420 } 426 }
421 } 427 }
422 public override float CollisionScore { 428 public override float CollisionScore {
@@ -440,10 +446,10 @@ public sealed class BSPrim : PhysicsActor
440 set { 446 set {
441 _orientation = value; 447 _orientation = value;
442 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
443 _scene.TaintedObject(delegate() 449 _scene.TaintedObject("BSPrim.setOrientation", delegate()
444 { 450 {
445 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
446 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 452 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
447 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
448 }); 454 });
449 } 455 }
@@ -457,7 +463,7 @@ public sealed class BSPrim : PhysicsActor
457 get { return _isPhysical; } 463 get { return _isPhysical; }
458 set { 464 set {
459 _isPhysical = value; 465 _isPhysical = value;
460 _scene.TaintedObject(delegate() 466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
461 { 467 {
462 SetObjectDynamic(); 468 SetObjectDynamic();
463 }); 469 });
@@ -478,7 +484,6 @@ public sealed class BSPrim : PhysicsActor
478 484
479 // Make gravity work if the object is physical and not selected 485 // Make gravity work if the object is physical and not selected
480 // No locking here because only called when it is safe 486 // No locking here because only called when it is safe
481 // Only called at taint time so it is save to call into Bullet.
482 private void SetObjectDynamic() 487 private void SetObjectDynamic()
483 { 488 {
484 // RA: remove this for the moment. 489 // RA: remove this for the moment.
@@ -487,13 +492,13 @@ public sealed class BSPrim : PhysicsActor
487 // Maybe a VerifyCorrectPhysicalShape() routine? 492 // Maybe a VerifyCorrectPhysicalShape() routine?
488 // RecreateGeomAndObject(); 493 // RecreateGeomAndObject();
489 494
490 float mass = _mass; 495 // Bullet wants static objects to have a mass of zero
491 // Bullet wants static objects have a mass of zero 496 float mass = IsStatic ? 0f : _mass;
492 if (IsStatic)
493 mass = 0f;
494 497
495 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
499
500 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
501 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
497 } 502 }
498 503
499 // prims don't fly 504 // prims don't fly
@@ -548,9 +553,9 @@ public sealed class BSPrim : PhysicsActor
548 set { 553 set {
549 _rotationalVelocity = value; 554 _rotationalVelocity = value;
550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 555 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
551 _scene.TaintedObject(delegate() 556 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
552 { 557 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 558 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 559 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
555 }); 560 });
556 } 561 }
@@ -565,9 +570,9 @@ public sealed class BSPrim : PhysicsActor
565 get { return _buoyancy; } 570 get { return _buoyancy; }
566 set { 571 set {
567 _buoyancy = value; 572 _buoyancy = value;
568 _scene.TaintedObject(delegate() 573 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
569 { 574 {
570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 575 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 576 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 }); 577 });
573 } 578 }
@@ -607,6 +612,7 @@ public sealed class BSPrim : PhysicsActor
607 612
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 613 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
609 public override void AddForce(OMV.Vector3 force, bool pushforce) { 614 public override void AddForce(OMV.Vector3 force, bool pushforce) {
615 // for an object, doesn't matter if force is a pushforce or not
610 if (force.IsFinite()) 616 if (force.IsFinite())
611 { 617 {
612 // _force += force; 618 // _force += force;
@@ -618,40 +624,48 @@ public sealed class BSPrim : PhysicsActor
618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 624 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return; 625 return;
620 } 626 }
621 _scene.TaintedObject(delegate() 627 _scene.TaintedObject("BSPrim.AddForce", delegate()
622 { 628 {
629 OMV.Vector3 fSum = OMV.Vector3.Zero;
623 lock (m_accumulatedForces) 630 lock (m_accumulatedForces)
624 { 631 {
625 if (m_accumulatedForces.Count > 0) 632 foreach (OMV.Vector3 v in m_accumulatedForces)
626 { 633 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero; 634 fSum += v;
628 foreach (OMV.Vector3 v in m_accumulatedForces)
629 {
630 fSum += v;
631 }
632 m_accumulatedForces.Clear();
633
634 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
635 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
636 } 635 }
636 m_accumulatedForces.Clear();
637 } 637 }
638 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
639 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
638 }); 640 });
639 } 641 }
640 642
641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 643 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 644 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
643 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 645 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
644 } 646 }
645 public override void SetMomentum(OMV.Vector3 momentum) { 647 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); 648 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
647 } 649 }
648 public override void SubscribeEvents(int ms) { 650 public override void SubscribeEvents(int ms) {
649 _subscribedEventsMs = ms; 651 _subscribedEventsMs = ms;
650 // make sure first collision happens 652 if (ms > 0)
651 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; 653 {
654 // make sure first collision happens
655 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
656
657 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
658 {
659 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
660 });
661 }
652 } 662 }
653 public override void UnSubscribeEvents() { 663 public override void UnSubscribeEvents() {
654 _subscribedEventsMs = 0; 664 _subscribedEventsMs = 0;
665 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
666 {
667 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
668 });
655 } 669 }
656 public override bool SubscribedEvents() { 670 public override bool SubscribedEvents() {
657 return (_subscribedEventsMs > 0); 671 return (_subscribedEventsMs > 0);
@@ -970,26 +984,26 @@ public sealed class BSPrim : PhysicsActor
970 { 984 {
971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 985 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
972 { 986 {
973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 987 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
974 { 988 // {
975 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
977 { 991 {
978 DetailLog("{0},CreateGeom,sphere", LocalID); 992 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // Bullet native objects are scaled by the Bullet engine so pass the size in 994 // Bullet native objects are scaled by the Bullet engine so pass the size in
981 _scale = _size; 995 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 996 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true; 997 ret = true;
984 } 998 }
985 } 999 // }
986 } 1000 }
987 else 1001 else
988 { 1002 {
989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1003 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1004 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
991 { 1005 {
992 DetailLog("{0},CreateGeom,box", LocalID); 1006 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1007 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size; 1008 _scale = _size;
995 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1009 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1032,12 +1046,12 @@ public sealed class BSPrim : PhysicsActor
1032 // if this new shape is the same as last time, don't recreate the mesh 1046 // if this new shape is the same as last time, don't recreate the mesh
1033 if (_meshKey == newMeshKey) return; 1047 if (_meshKey == newMeshKey) return;
1034 1048
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); 1049 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1036 // Since we're recreating new, get rid of any previously generated shape 1050 // Since we're recreating new, get rid of any previously generated shape
1037 if (_meshKey != 0) 1051 if (_meshKey != 0)
1038 { 1052 {
1039 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1053 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1054 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1055 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1042 _mesh = null; 1056 _mesh = null;
1043 _meshKey = 0; 1057 _meshKey = 0;
@@ -1067,7 +1081,7 @@ public sealed class BSPrim : PhysicsActor
1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1081 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1068 // meshes are already scaled by the meshmerizer 1082 // meshes are already scaled by the meshmerizer
1069 _scale = new OMV.Vector3(1f, 1f, 1f); 1083 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID); 1084 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1071 return; 1085 return;
1072 } 1086 }
1073 1087
@@ -1081,17 +1095,17 @@ public sealed class BSPrim : PhysicsActor
1081 // if the hull hasn't changed, don't rebuild it 1095 // if the hull hasn't changed, don't rebuild it
1082 if (newHullKey == _hullKey) return; 1096 if (newHullKey == _hullKey) return;
1083 1097
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); 1098 DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey);
1085 1099
1086 // Since we're recreating new, get rid of any previously generated shape 1100 // Since we're recreating new, get rid of any previously generated shape
1087 if (_hullKey != 0) 1101 if (_hullKey != 0)
1088 { 1102 {
1089 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1103 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); 1104 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1105 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1092 _hullKey = 0; 1106 _hullKey = 0;
1093 _hulls.Clear(); 1107 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); 1108 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1109 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1096 _mesh = null; // the mesh cannot match either 1110 _mesh = null; // the mesh cannot match either
1097 _meshKey = 0; 1111 _meshKey = 0;
@@ -1188,7 +1202,7 @@ public sealed class BSPrim : PhysicsActor
1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1202 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1189 // meshes are already scaled by the meshmerizer 1203 // meshes are already scaled by the meshmerizer
1190 _scale = new OMV.Vector3(1f, 1f, 1f); 1204 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID); 1205 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1192 return; 1206 return;
1193 } 1207 }
1194 1208
@@ -1214,7 +1228,7 @@ public sealed class BSPrim : PhysicsActor
1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1228 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1215 1229
1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1230 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); 1231 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1218 1232
1219 return ret; 1233 return ret;
1220 } 1234 }
@@ -1326,20 +1340,18 @@ public sealed class BSPrim : PhysicsActor
1326 1340
1327 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1341 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1328 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1342 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1329 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1343 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1344 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331 1345
1332 base.RequestPhysicsterseUpdate(); 1346 base.RequestPhysicsterseUpdate();
1333 } 1347 }
1334 /*
1335 else 1348 else
1336 { 1349 {
1337 // For debugging, we also report the movement of children 1350 // For debugging, we also report the movement of children
1338 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1351 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1339 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1352 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1340 entprop.Acceleration, entprop.RotationalVelocity); 1353 entprop.Acceleration, entprop.RotationalVelocity);
1341 } 1354 }
1342 */
1343 } 1355 }
1344 1356
1345 // I've collided with something 1357 // I've collided with something
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 011033c..beaea1f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
75 75
76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } 76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); }
77 77
78 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
79 79
@@ -162,14 +162,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
162 } 162 }
163 163
164 public delegate void TaintCallback(); 164 public delegate void TaintCallback();
165 private List<TaintCallback> _taintedObjects; 165 private struct TaintCallbackEntry
166 {
167 public String ident;
168 public TaintCallback callback;
169 public TaintCallbackEntry(string i, TaintCallback c)
170 {
171 ident = i;
172 callback = c;
173 }
174 }
175 private List<TaintCallbackEntry> _taintedObjects;
166 private Object _taintLock = new Object(); 176 private Object _taintLock = new Object();
167 177
168 // A pointer to an instance if this structure is passed to the C++ code 178 // A pointer to an instance if this structure is passed to the C++ code
169 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
170 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
171 181
172 public bool shouldDebugLog { get; private set; } 182 public bool ShouldDebugLog { get; private set; }
173 183
174 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
175 185
@@ -232,7 +242,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
232 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
233 } 243 }
234 244
235 _taintedObjects = new List<TaintCallback>(); 245 _taintedObjects = new List<TaintCallbackEntry>();
236 246
237 mesher = meshmerizer; 247 mesher = meshmerizer;
238 // The bounding box for the simulated world 248 // The bounding box for the simulated world
@@ -245,7 +255,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
245 255
246 // Initialization to support the transition to a new API which puts most of the logic 256 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to. 257 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); 258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World); 259 m_constraintCollection = new BSConstraintCollection(World);
250 260
251 m_initialized = true; 261 m_initialized = true;
@@ -352,7 +362,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
352 BSPrim bsprim = prim as BSPrim; 362 BSPrim bsprim = prim as BSPrim;
353 if (bsprim != null) 363 if (bsprim != null)
354 { 364 {
355 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 365 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
356 try 367 try
357 { 368 {
358 lock (m_prims) m_prims.Remove(bsprim.LocalID); 369 lock (m_prims) m_prims.Remove(bsprim.LocalID);
@@ -377,6 +388,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
377 388
378 if (!m_initialized) return null; 389 if (!m_initialized) return null;
379 390
391 DetailLog("{0},AddPrimShape,call", localID);
392
380 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
381 lock (m_prims) m_prims.Add(localID, prim); 394 lock (m_prims) m_prims.Add(localID, prim);
382 return prim; 395 return prim;
@@ -416,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
416 { 429 {
417 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
418 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
419 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 432 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
420 } 433 }
421 catch (Exception e) 434 catch (Exception e)
422 { 435 {
423 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
424 DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 437 DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
425 // updatedEntityCount = 0; 438 // updatedEntityCount = 0;
426 collidersCount = 0; 439 collidersCount = 0;
427 } 440 }
@@ -535,7 +548,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
535 548
536 public override void SetTerrain(float[] heightMap) { 549 public override void SetTerrain(float[] heightMap) {
537 m_heightMap = heightMap; 550 m_heightMap = heightMap;
538 this.TaintedObject(delegate() 551 this.TaintedObject("BSScene.SetTerrain", delegate()
539 { 552 {
540 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); 553 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
541 }); 554 });
@@ -727,12 +740,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
727 // Calls to the PhysicsActors can't directly call into the physics engine 740 // Calls to the PhysicsActors can't directly call into the physics engine
728 // because it might be busy. We delay changes to a known time. 741 // because it might be busy. We delay changes to a known time.
729 // We rely on C#'s closure to save and restore the context for the delegate. 742 // We rely on C#'s closure to save and restore the context for the delegate.
730 public void TaintedObject(TaintCallback callback) 743 public void TaintedObject(String ident, TaintCallback callback)
731 { 744 {
732 if (!m_initialized) return; 745 if (!m_initialized) return;
733 746
734 lock (_taintLock) 747 lock (_taintLock)
735 _taintedObjects.Add(callback); 748 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
736 return; 749 return;
737 } 750 }
738 751
@@ -744,22 +757,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
744 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 757 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
745 { 758 {
746 // swizzle a new list into the list location so we can process what's there 759 // swizzle a new list into the list location so we can process what's there
747 List<TaintCallback> oldList; 760 List<TaintCallbackEntry> oldList;
748 lock (_taintLock) 761 lock (_taintLock)
749 { 762 {
750 oldList = _taintedObjects; 763 oldList = _taintedObjects;
751 _taintedObjects = new List<TaintCallback>(); 764 _taintedObjects = new List<TaintCallbackEntry>();
752 } 765 }
753 766
754 foreach (TaintCallback callback in oldList) 767 foreach (TaintCallbackEntry tcbe in oldList)
755 { 768 {
756 try 769 try
757 { 770 {
758 callback(); 771 tcbe.callback();
759 } 772 }
760 catch (Exception e) 773 catch (Exception e)
761 { 774 {
762 m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e); 775 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
763 } 776 }
764 } 777 }
765 oldList.Clear(); 778 oldList.Clear();
@@ -767,6 +780,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
767 } 780 }
768 781
769 #region Vehicles 782 #region Vehicles
783
784 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
785 {
786 if (newType == Vehicle.TYPE_NONE)
787 {
788 RemoveVehiclePrim(vehic);
789 }
790 else
791 {
792 // make it so the scene will call us each tick to do vehicle things
793 AddVehiclePrim(vehic);
794 }
795 }
796
770 // Make so the scene will call this prim for vehicle actions each tick. 797 // Make so the scene will call this prim for vehicle actions each tick.
771 // Safe to call if prim is already in the vehicle list. 798 // Safe to call if prim is already in the vehicle list.
772 public void AddVehiclePrim(BSPrim vehicle) 799 public void AddVehiclePrim(BSPrim vehicle)
@@ -812,12 +839,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
812 839
813 private struct ParameterDefn 840 private struct ParameterDefn
814 { 841 {
815 public string name; 842 public string name; // string name of the parameter
816 public string desc; 843 public string desc; // a short description of what the parameter means
817 public float defaultValue; 844 public float defaultValue; // default value if not specified anywhere else
818 public ParamUser userParam; 845 public ParamUser userParam; // get the value from the configuration file
819 public ParamGet getter; 846 public ParamGet getter; // return the current value stored for this parameter
820 public ParamSet setter; 847 public ParamSet setter; // set the current value for this parameter
821 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 848 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
822 { 849 {
823 name = n; 850 name = n;
@@ -834,7 +861,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
834 // To add a new externally referencable/settable parameter, add the paramter storage 861 // To add a new externally referencable/settable parameter, add the paramter storage
835 // location somewhere in the program and make an entry in this table with the 862 // location somewhere in the program and make an entry in this table with the
836 // getters and setters. 863 // getters and setters.
837 // To add a new variable, it is easiest to find an existing definition and copy it. 864 // It is easiest to find an existing definition and copy it.
838 // Parameter values are floats. Booleans are converted to a floating value. 865 // Parameter values are floats. Booleans are converted to a floating value.
839 // 866 //
840 // A ParameterDefn() takes the following parameters: 867 // A ParameterDefn() takes the following parameters:
@@ -870,7 +897,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
870 (s) => { return (float)s.m_meshLOD; }, 897 (s) => { return (float)s.m_meshLOD; },
871 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 898 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
872 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 899 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
873 32, 900 32f,
874 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 901 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
875 (s) => { return (float)s.m_sculptLOD; }, 902 (s) => { return (float)s.m_sculptLOD; },
876 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 903 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
@@ -1027,14 +1054,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1027 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1054 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1028 1055
1029 1056
1030 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", 1057 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1031 0f, // zero to disable 1058 0f, // zero to disable
1032 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1059 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1033 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1060 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1034 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1061 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1062 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1063 0f, // zero to disable
1064 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1065 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1066 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1035 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 1067 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1036 ConfigurationParameters.numericTrue, 1068 ConfigurationParameters.numericFalse,
1037 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1069 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1038 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, 1070 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1039 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), 1071 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1040 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 1072 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
@@ -1101,9 +1133,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1101 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1133 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1102 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", 1134 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1103 ConfigurationParameters.numericFalse, 1135 ConfigurationParameters.numericFalse,
1104 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, 1136 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1105 (s) => { return s.NumericBool(s.shouldDebugLog); }, 1137 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1106 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), 1138 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1107 1139
1108 }; 1140 };
1109 1141
@@ -1243,7 +1275,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1243 List<uint> objectIDs = lIDs; 1275 List<uint> objectIDs = lIDs;
1244 string xparm = parm.ToLower(); 1276 string xparm = parm.ToLower();
1245 float xval = val; 1277 float xval = val;
1246 TaintedObject(delegate() { 1278 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1247 foreach (uint lID in objectIDs) 1279 foreach (uint lID in objectIDs)
1248 { 1280 {
1249 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1281 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
@@ -1263,7 +1295,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1263 uint xlocalID = localID; 1295 uint xlocalID = localID;
1264 string xparm = parm.ToLower(); 1296 string xparm = parm.ToLower();
1265 float xval = val; 1297 float xval = val;
1266 TaintedObject(delegate() { 1298 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1267 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1299 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
1268 }); 1300 });
1269 } 1301 }
@@ -1289,10 +1321,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1289 #endregion Runtime settable parameters 1321 #endregion Runtime settable parameters
1290 1322
1291 // Invoke the detailed logger and output something if it's enabled. 1323 // Invoke the detailed logger and output something if it's enabled.
1292 private void DetailLog(string msg, params Object[] args) 1324 public void DetailLog(string msg, params Object[] args)
1293 { 1325 {
1294 PhysicsLogging.Write(msg, args); 1326 PhysicsLogging.Write(msg, args);
1295 } 1327 }
1328 // used to fill in the LocalID when there isn't one
1329 public const string DetailLogZero = "0000000000";
1296 1330
1297} 1331}
1298} 1332}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 0ffbc94..6800b96 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -35,9 +35,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin {
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36public struct BulletSim 36public struct BulletSim
37{ 37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } 38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID; 39 public uint ID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene;
42 public IntPtr Ptr;
41} 43}
42 44
43public struct BulletBody 45public struct BulletBody
@@ -158,6 +160,7 @@ public struct ConfigurationParameters
158 public float avatarContactProcessingThreshold; 160 public float avatarContactProcessingThreshold;
159 161
160 public float maxPersistantManifoldPoolSize; 162 public float maxPersistantManifoldPoolSize;
163 public float maxCollisionAlgorithmPoolSize;
161 public float shouldDisableContactPoolDynamicAllocation; 164 public float shouldDisableContactPoolDynamicAllocation;
162 public float shouldForceUpdateAllAabbs; 165 public float shouldForceUpdateAllAabbs;
163 public float shouldRandomizeSolverOrder; 166 public float shouldRandomizeSolverOrder;
@@ -179,17 +182,18 @@ public struct ConfigurationParameters
179// Values used by Bullet and BulletSim to control collisions 182// Values used by Bullet and BulletSim to control collisions
180public enum CollisionFlags : uint 183public enum CollisionFlags : uint
181{ 184{
182 STATIC_OBJECT = 1 << 0, 185 CF_STATIC_OBJECT = 1 << 0,
183 KINEMATIC_OBJECT = 1 << 1, 186 CF_KINEMATIC_OBJECT = 1 << 1,
184 NO_CONTACT_RESPONSE = 1 << 2, 187 CF_NO_CONTACT_RESPONSE = 1 << 2,
185 CUSTOM_MATERIAL_CALLBACK = 1 << 3, 188 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
186 CHARACTER_OBJECT = 1 << 4, 189 CF_CHARACTER_OBJECT = 1 << 4,
187 DISABLE_VISUALIZE_OBJECT = 1 << 5, 190 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
188 DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
189 // Following used by BulletSim to control collisions 192 // Following used by BulletSim to control collisions
190 VOLUME_DETECT_OBJECT = 1 << 10, 193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
191 PHANTOM_OBJECT = 1 << 11, 194 BS_VOLUME_DETECT_OBJECT = 1 << 11,
192 PHYSICAL_OBJECT = 1 << 12, 195 BS_PHANTOM_OBJECT = 1 << 12,
196 BS_PHYSICAL_OBJECT = 1 << 13,
193}; 197};
194 198
195// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -361,7 +365,7 @@ public static extern IntPtr GetSimHandle2(uint worldID);
361public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); 365public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
362 366
363[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
364public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); 368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
365 369
366// =============================================================================== 370// ===============================================================================
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -370,40 +374,43 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
370 int maxUpdates, IntPtr updateArray); 374 int maxUpdates, IntPtr updateArray);
371 375
372[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
373public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); 377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
374 378
375[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
376public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); 380public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
377 381
378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
379public static extern void Shutdown2(IntPtr sim); 383public static extern void Shutdown2(IntPtr sim);
380 384
381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
382public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, 386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
383 out int updatedEntityCount, 387 out int updatedEntityCount,
384 out IntPtr updatedEntitiesPtr, 388 out IntPtr updatedEntitiesPtr,
385 out int collidersCount, 389 out int collidersCount,
386 out IntPtr collidersPtr); 390 out IntPtr collidersPtr);
387 391
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj);
394
388/* 395/*
389[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
390public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); 397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
391 398
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); 400public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
394 401
395[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
396public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); 403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
397 404
398[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
399public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); 406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
400 407
401[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
402public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); 409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
403*/ 410*/
404 411
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, 413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
407 Vector3 frame1loc, Quaternion frame1rot, 414 Vector3 frame1loc, Quaternion frame1rot,
408 Vector3 frame2loc, Quaternion frame2rot, 415 Vector3 frame2loc, Quaternion frame2rot,
409 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
@@ -427,7 +434,13 @@ public static extern bool CalculateTransforms2(IntPtr constrain);
427public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 434public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
428 435
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 436[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 437public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
440public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
441
442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
443public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
431 444
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern Vector3 GetPosition2(IntPtr obj); 446public static extern Vector3 GetPosition2(IntPtr obj);
@@ -448,6 +461,9 @@ public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocit
448public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 461public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
449 462
450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
465
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
451public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 467public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
452 468
453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -478,13 +494,16 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
478public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 494public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
479 495
480[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
481public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); 497public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
498
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
482 501
483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
484public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); 503public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
485 504
486[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
487public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); 506public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
488 507
489[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
490public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 509public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
@@ -505,12 +524,6 @@ public static extern bool SetMargin2(IntPtr obj, float val);
505public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 524public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
506 525
507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
508public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
509
510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
511public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
512
513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
514public static extern bool DestroyObject2(IntPtr world, uint id); 527public static extern bool DestroyObject2(IntPtr world, uint id);
515 528
516[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 7237d1d..54cb214 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3346,7 +3346,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3346 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3346 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3347 3347
3348 if (attachmentsModule != null) 3348 if (attachmentsModule != null)
3349 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true); 3349 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
3350 else 3350 else
3351 return false; 3351 return false;
3352 } 3352 }
@@ -5375,12 +5375,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5375 { 5375 {
5376 return 0; 5376 return 0;
5377 } 5377 }
5378
5379 // Vectors & Rotations always return zero in SL, but
5380 // keys don't always return zero, it seems to be a bit complex.
5381 else if (src.Data[index] is LSL_Vector ||
5382 src.Data[index] is LSL_Rotation)
5383 {
5384 return 0;
5385 }
5378 try 5386 try
5379 { 5387 {
5388
5380 if (src.Data[index] is LSL_Integer) 5389 if (src.Data[index] is LSL_Integer)
5381 return (LSL_Integer) src.Data[index]; 5390 return (LSL_Integer)src.Data[index];
5382 else if (src.Data[index] is LSL_Float) 5391 else if (src.Data[index] is LSL_Float)
5383 return Convert.ToInt32(((LSL_Float) src.Data[index]).value); 5392 return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
5384 return new LSL_Integer(src.Data[index].ToString()); 5393 return new LSL_Integer(src.Data[index].ToString());
5385 } 5394 }
5386 catch (FormatException) 5395 catch (FormatException)
@@ -5400,12 +5409,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5400 { 5409 {
5401 return 0.0; 5410 return 0.0;
5402 } 5411 }
5412
5413 // Vectors & Rotations always return zero in SL
5414 else if (src.Data[index] is LSL_Vector ||
5415 src.Data[index] is LSL_Rotation)
5416 {
5417 return 0;
5418 }
5419 // valid keys seem to get parsed as integers then converted to floats
5420 else
5421 {
5422 UUID uuidt;
5423 if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
5424 {
5425 return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
5426 }
5427 }
5403 try 5428 try
5404 { 5429 {
5405 if (src.Data[index] is LSL_Integer) 5430 if (src.Data[index] is LSL_Integer)
5406 return Convert.ToDouble(((LSL_Integer) src.Data[index]).value); 5431 return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
5407 else if (src.Data[index] is LSL_Float) 5432 else if (src.Data[index] is LSL_Float)
5408 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5433 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
5409 else if (src.Data[index] is LSL_String) 5434 else if (src.Data[index] is LSL_String)
5410 { 5435 {
5411 string str = ((LSL_String) src.Data[index]).m_string; 5436 string str = ((LSL_String) src.Data[index]).m_string;
@@ -5443,17 +5468,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5443 return src.Data[index].ToString(); 5468 return src.Data[index].ToString();
5444 } 5469 }
5445 5470
5446 public LSL_String llList2Key(LSL_List src, int index) 5471 public LSL_Key llList2Key(LSL_List src, int index)
5447 { 5472 {
5448 m_host.AddScriptLPS(1); 5473 m_host.AddScriptLPS(1);
5449 if (index < 0) 5474 if (index < 0)
5450 { 5475 {
5451 index = src.Length + index; 5476 index = src.Length + index;
5452 } 5477 }
5478
5453 if (index >= src.Length || index < 0) 5479 if (index >= src.Length || index < 0)
5454 { 5480 {
5455 return ""; 5481 return "";
5456 } 5482 }
5483
5484 // SL spits out an empty string for types other than key & string
5485 // At the time of patching, LSL_Key is currently LSL_String,
5486 // so the OR check may be a little redundant, but it's being done
5487 // for completion and should LSL_Key ever be implemented
5488 // as it's own struct
5489 else if (!(src.Data[index] is LSL_String ||
5490 src.Data[index] is LSL_Key))
5491 {
5492 return "";
5493 }
5494
5457 return src.Data[index].ToString(); 5495 return src.Data[index].ToString();
5458 } 5496 }
5459 5497
@@ -5472,6 +5510,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5472 { 5510 {
5473 return (LSL_Vector)src.Data[index]; 5511 return (LSL_Vector)src.Data[index];
5474 } 5512 }
5513
5514 // SL spits always out ZERO_VECTOR for anything other than
5515 // strings or vectors. Although keys always return ZERO_VECTOR,
5516 // it is currently difficult to make the distinction between
5517 // a string, a key as string and a string that by coincidence
5518 // is a string, so we're going to leave that up to the
5519 // LSL_Vector constructor.
5520 else if (!(src.Data[index] is LSL_String ||
5521 src.Data[index] is LSL_Vector))
5522 {
5523 return new LSL_Vector(0, 0, 0);
5524 }
5475 else 5525 else
5476 { 5526 {
5477 return new LSL_Vector(src.Data[index].ToString()); 5527 return new LSL_Vector(src.Data[index].ToString());
@@ -5489,7 +5539,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5489 { 5539 {
5490 return new LSL_Rotation(0, 0, 0, 1); 5540 return new LSL_Rotation(0, 0, 0, 1);
5491 } 5541 }
5492 if (src.Data[index].GetType() == typeof(LSL_Rotation)) 5542
5543 // SL spits always out ZERO_ROTATION for anything other than
5544 // strings or vectors. Although keys always return ZERO_ROTATION,
5545 // it is currently difficult to make the distinction between
5546 // a string, a key as string and a string that by coincidence
5547 // is a string, so we're going to leave that up to the
5548 // LSL_Rotation constructor.
5549 else if (!(src.Data[index] is LSL_String ||
5550 src.Data[index] is LSL_Rotation))
5551 {
5552 return new LSL_Rotation(0, 0, 0, 1);
5553 }
5554 else if (src.Data[index].GetType() == typeof(LSL_Rotation))
5493 { 5555 {
5494 return (LSL_Rotation)src.Data[index]; 5556 return (LSL_Rotation)src.Data[index];
5495 } 5557 }
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
index 8412c35..0caa521 100644
--- a/OpenSim/Services/Interfaces/IAvatarService.cs
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -182,7 +182,8 @@ namespace OpenSim.Services.Interfaces
182 List<AvatarAttachment> attachments = appearance.GetAttachments(); 182 List<AvatarAttachment> attachments = appearance.GetAttachments();
183 foreach (AvatarAttachment attach in attachments) 183 foreach (AvatarAttachment attach in attachments)
184 { 184 {
185 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); 185 if (attach.ItemID != UUID.Zero)
186 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
186 } 187 }
187 } 188 }
188 189
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index ced0bce..2571669 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -181,11 +181,6 @@
181 ; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago 181 ; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago
182 MaximumTimeBeforePersistenceConsidered = 600 182 MaximumTimeBeforePersistenceConsidered = 600
183 183
184 ; Experimental setting to resend appearance updates every 60 seconds.
185 ; These packets are small and this can help with grey avatar syndrome.
186 ; Default is false
187 SendPeriodicAppearanceUpdates = false
188
189 ; ## 184 ; ##
190 ; ## PHYSICS 185 ; ## PHYSICS
191 ; ## 186 ; ##
@@ -341,27 +336,12 @@
341 ; OpenJPEG if false 336 ; OpenJPEG if false
342 ; UseCSJ2K = true 337 ; UseCSJ2K = true
343 338
344
345 ; Use "Trash" folder for items deleted from the scene 339 ; Use "Trash" folder for items deleted from the scene
346 ; When set to True (the default) items deleted from the scene will be 340 ; When set to True (the default) items deleted from the scene will be
347 ; stored in the user's trash or lost and found folder. When set to 341 ; stored in the user's trash or lost and found folder. When set to
348 ; False items will be removed from the scene permanently 342 ; False items will be removed from the scene permanently
349 UseTrashOnDelete = True 343 UseTrashOnDelete = True
350 344
351 ; Persist avatar baked textures
352 ; Persisting baked textures can speed up login and region border
353 ; crossings especially with large numbers of users, though it
354 ; will store potentially large numbers of textures in your asset
355 ; database
356 PersistBakedTextures = false
357
358 ; Control the delay before appearance is sent to other avatars and
359 ; saved in the avatar service. Attempts to limit the impact caused
360 ; by the very chatty dialog that sets appearance when an avatar
361 ; logs in or teleports into a region; values are in seconds
362 DelayBeforeAppearanceSave = 5
363 DelayBeforeAppearanceSend = 2
364
365 345
366[RegionReady] 346[RegionReady]
367 ; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled 347 ; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled
@@ -671,6 +651,28 @@
671 CoalesceMultipleObjectsToInventory = true 651 CoalesceMultipleObjectsToInventory = true
672 652
673 653
654[Appearance]
655 ; Persist avatar baked textures
656 ; Persisting baked textures can speed up login and region border
657 ; crossings especially with large numbers of users, though it
658 ; will store potentially large numbers of textures in your asset
659 ; database
660 PersistBakedTextures = false
661
662 ; Control the delay before appearance is sent to other avatars and
663 ; saved in the avatar service. Attempts to limit the impact caused
664 ; by the very chatty dialog that sets appearance when an avatar
665 ; logs in or teleports into a region; values are in seconds
666 DelayBeforeAppearanceSave = 5
667 DelayBeforeAppearanceSend = 2
668
669 ; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds.
670 ; This may help with some situations where avatars are persistently grey, though it will not help
671 ; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others).
672 ; This setting is experimental.
673 ResendAppearanceUpdates = false
674
675
674[Attachments] 676[Attachments]
675 ; Controls whether avatar attachments are enabled. 677 ; Controls whether avatar attachments are enabled.
676 ; Defaults to true - only set to false for debugging purposes 678 ; Defaults to true - only set to false for debugging purposes
@@ -937,7 +939,7 @@
937 FixedTimeStep = .01667 939 FixedTimeStep = .01667
938 940
939 MaxCollisionsPerFrame = 2048 941 MaxCollisionsPerFrame = 2048
940 MaxUpdatesPerFrame = 2048 942 MaxUpdatesPerFrame = 8192
941 943
942[RemoteAdmin] 944[RemoteAdmin]
943 enabled = false 945 enabled = false
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 03e8f26..f4953f9 100755
--- a/bin/lib32/BulletSim.dll
+++ b/bin/lib32/BulletSim.dll
Binary files differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index 4e119c4..2b5702d 100755
--- a/bin/lib32/libBulletSim.so
+++ b/bin/lib32/libBulletSim.so
Binary files differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index 6e8d6b4..be191c0 100755
--- a/bin/lib64/BulletSim.dll
+++ b/bin/lib64/BulletSim.dll
Binary files differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index 9363d1a..fc51b39 100755
--- a/bin/lib64/libBulletSim.so
+++ b/bin/lib64/libBulletSim.so
Binary files differ