aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs36
-rw-r--r--OpenSim/Data/IXInventoryData.cs10
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs457
-rw-r--r--OpenSim/Framework/Cache.cs83
-rw-r--r--OpenSim/Framework/Constants.cs1
-rw-r--r--OpenSim/Framework/IClientAPI.cs15
-rw-r--r--OpenSim/Framework/InventoryFolderBase.cs18
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs15
-rw-r--r--OpenSim/Framework/RegionInfo.cs60
-rw-r--r--OpenSim/Framework/Serialization/External/OspResolver.cs14
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/Util.cs6
-rw-r--r--OpenSim/Region/Application/OpenSim.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs15
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs64
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs277
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs49
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs281
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs142
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs63
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs69
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs29
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUrlModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs78
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs109
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs32
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs36
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs50
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs151
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs7
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs237
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs93
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs64
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs272
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs437
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs464
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs559
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs3
-rw-r--r--OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml14
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1329
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs24
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs254
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs91
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs53
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs26
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs28
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs77
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs24
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs57
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs41
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs4
-rw-r--r--OpenSim/Services/GridService/GridService.cs53
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs65
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs4
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs6
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs131
-rw-r--r--OpenSim/Tests/Common/TestHelpers.cs1
-rw-r--r--OpenSim/Tests/Performance/NPCPerformanceTests.cs (renamed from OpenSim/Tests/Torture/NPCTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ObjectPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ObjectTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ScriptPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ScriptTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs132
89 files changed, 5051 insertions, 2030 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index f040ff7..8d25e18 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
163 163
164 if (texture == null) 164 if (texture == null)
165 { 165 {
166 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); 166// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
167 167
168 // Fetch locally or remotely. Misses return a 404 168 // Fetch locally or remotely. Misses return a 404
169 texture = m_assetService.Get(textureID.ToString()); 169 texture = m_assetService.Get(textureID.ToString());
@@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
197 } 197 }
198 else // it was on the cache 198 else // it was on the cache
199 { 199 {
200 //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); 200// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
201 WriteTextureData(httpRequest, httpResponse, texture, format); 201 WriteTextureData(httpRequest, httpResponse, texture, format);
202 return true; 202 return true;
203 } 203 }
@@ -219,14 +219,30 @@ namespace OpenSim.Capabilities.Handlers
219 int start, end; 219 int start, end;
220 if (TryParseRange(range, out start, out end)) 220 if (TryParseRange(range, out start, out end))
221 { 221 {
222
223 // Before clamping start make sure we can satisfy it in order to avoid 222 // Before clamping start make sure we can satisfy it in order to avoid
224 // sending back the last byte instead of an error status 223 // sending back the last byte instead of an error status
225 if (start >= texture.Data.Length) 224 if (start >= texture.Data.Length)
226 { 225 {
226// m_log.DebugFormat(
227// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
228// texture.ID, start, texture.Data.Length);
229
230 // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
231 // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
232 // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
233 // received a very small texture may attempt to fetch bytes from the server past the
234 // range of data that it received originally. Whether this happens appears to depend on whether
235 // the viewer's estimation of how large a request it needs to make for certain discard levels
236 // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
237 // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
238 // here will cause the viewer to treat the texture as bad and never display the full resolution
239 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
240
227// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 241// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
228 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters 242// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
229 response.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 243// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
244 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
245 response.ContentType = texture.Metadata.ContentType;
230 } 246 }
231 else 247 else
232 { 248 {
@@ -234,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
234 start = Utils.Clamp(start, 0, end); 250 start = Utils.Clamp(start, 0, end);
235 int len = end - start + 1; 251 int len = end - start + 1;
236 252
237 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 253// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
238 254
239 // Always return PartialContent, even if the range covered the entire data length 255 // Always return PartialContent, even if the range covered the entire data length
240 // We were accidentally sending back 404 before in this situation 256 // We were accidentally sending back 404 before in this situation
241 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the 257 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
242 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. 258 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
259 //
260 // We also do not want to send back OK even if the whole range was satisfiable since this causes
261 // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
262// if (end > maxEnd)
263// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
264// else
243 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 265 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
244 266
245 response.ContentLength = len; 267 response.ContentLength = len;
@@ -368,4 +390,4 @@ namespace OpenSim.Capabilities.Handlers
368 return null; 390 return null;
369 } 391 }
370 } 392 }
371} \ No newline at end of file 393}
diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index 85a5c08..e64a828 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -40,6 +40,11 @@ namespace OpenSim.Data
40 public UUID folderID; 40 public UUID folderID;
41 public UUID agentID; 41 public UUID agentID;
42 public UUID parentFolderID; 42 public UUID parentFolderID;
43
44 public XInventoryFolder Clone()
45 {
46 return (XInventoryFolder)MemberwiseClone();
47 }
43 } 48 }
44 49
45 public class XInventoryItem 50 public class XInventoryItem
@@ -64,6 +69,11 @@ namespace OpenSim.Data
64 public UUID avatarID; 69 public UUID avatarID;
65 public UUID parentFolderID; 70 public UUID parentFolderID;
66 public int inventoryGroupPermissions; 71 public int inventoryGroupPermissions;
72
73 public XInventoryItem Clone()
74 {
75 return (XInventoryItem)MemberwiseClone();
76 }
67 } 77 }
68 78
69 public interface IXInventoryData 79 public interface IXInventoryData
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 4d7c0c9..12c979a 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -747,95 +747,99 @@ namespace OpenSim.Data.MySQL
747 RegionLightShareData nWP = new RegionLightShareData(); 747 RegionLightShareData nWP = new RegionLightShareData();
748 nWP.OnSave += StoreRegionWindlightSettings; 748 nWP.OnSave += StoreRegionWindlightSettings;
749 749
750 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 750 lock (m_dbLock)
751 { 751 {
752 dbcon.Open(); 752 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
753
754 string command = "select * from `regionwindlight` where region_id = ?regionID";
755
756 using (MySqlCommand cmd = new MySqlCommand(command))
757 { 753 {
758 cmd.Connection = dbcon; 754 dbcon.Open();
759 755
760 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); 756 string command = "select * from `regionwindlight` where region_id = ?regionID";
761 757
762 IDataReader result = ExecuteReader(cmd); 758 using (MySqlCommand cmd = new MySqlCommand(command))
763 if (!result.Read())
764 {
765 //No result, so store our default windlight profile and return it
766 nWP.regionID = regionUUID;
767 // StoreRegionWindlightSettings(nWP);
768 return nWP;
769 }
770 else
771 { 759 {
772 nWP.regionID = DBGuid.FromDB(result["region_id"]); 760 cmd.Connection = dbcon;
773 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); 761
774 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); 762 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
775 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); 763
776 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); 764 IDataReader result = ExecuteReader(cmd);
777 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); 765 if (!result.Read())
778 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); 766 {
779 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); 767 //No result, so store our default windlight profile and return it
780 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); 768 nWP.regionID = regionUUID;
781 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); 769// StoreRegionWindlightSettings(nWP);
782 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); 770 return nWP;
783 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); 771 }
784 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); 772 else
785 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); 773 {
786 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); 774 nWP.regionID = DBGuid.FromDB(result["region_id"]);
787 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); 775 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
788 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); 776 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
789 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); 777 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
790 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); 778 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
791 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); 779 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
792 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); 780 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
793 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); 781 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
794 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); 782 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
795 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); 783 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
796 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); 784 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
797 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); 785 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
798 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); 786 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
799 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); 787 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
800 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); 788 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
801 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); 789 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
802 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); 790 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
803 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); 791 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
804 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); 792 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
805 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); 793 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
806 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); 794 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
807 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); 795 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
808 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); 796 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
809 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); 797 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
810 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); 798 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
811 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); 799 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
812 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); 800 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
813 nWP.eastAngle = Convert.ToSingle(result["east_angle"]); 801 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
814 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); 802 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
815 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); 803 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
816 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); 804 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
817 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); 805 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
818 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); 806 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
819 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); 807 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
820 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); 808 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
821 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); 809 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
822 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); 810 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
823 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); 811 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
824 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); 812 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
825 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); 813 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
826 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); 814 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
827 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); 815 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
828 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); 816 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
829 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); 817 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
830 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); 818 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
831 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); 819 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
832 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); 820 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
833 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); 821 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
834 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); 822 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
835 nWP.valid = true; 823 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
824 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
825 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
826 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
827 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
828 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
829 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
830 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
831 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
832 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
833 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
834 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
835 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
836 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
837 nWP.valid = true;
838 }
836 } 839 }
837 } 840 }
838 } 841 }
842
839 return nWP; 843 return nWP;
840 } 844 }
841 845
@@ -881,118 +885,124 @@ namespace OpenSim.Data.MySQL
881 885
882 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl) 886 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
883 { 887 {
884 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 888 lock (m_dbLock)
885 { 889 {
886 dbcon.Open(); 890 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
887
888 using (MySqlCommand cmd = dbcon.CreateCommand())
889 { 891 {
890 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; 892 dbcon.Open();
891 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; 893
892 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; 894 using (MySqlCommand cmd = dbcon.CreateCommand())
893 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; 895 {
894 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; 896 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
895 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; 897 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
896 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; 898 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
897 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; 899 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
898 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; 900 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
899 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; 901 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
900 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; 902 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
901 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; 903 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
902 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; 904 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
903 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; 905 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
904 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; 906 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
905 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; 907 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
906 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; 908 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
907 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; 909 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
908 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; 910 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
909 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; 911 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
910 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; 912 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
911 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; 913 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
912 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; 914 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
913 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; 915 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
914 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; 916 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
915 917 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
916 cmd.Parameters.AddWithValue("region_id", wl.regionID); 918 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
917 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); 919 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
918 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); 920 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
919 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); 921
920 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); 922 cmd.Parameters.AddWithValue("region_id", wl.regionID);
921 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); 923 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
922 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); 924 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
923 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); 925 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
924 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); 926 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
925 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); 927 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
926 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); 928 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
927 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); 929 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
928 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); 930 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
929 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); 931 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
930 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); 932 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
931 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); 933 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
932 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); 934 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
933 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); 935 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
934 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); 936 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
935 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); 937 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
936 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); 938 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
937 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); 939 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
938 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); 940 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
939 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); 941 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
940 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); 942 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
941 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); 943 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
942 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); 944 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
943 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); 945 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
944 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); 946 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
945 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); 947 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
946 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); 948 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
947 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); 949 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
948 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); 950 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
949 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); 951 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
950 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); 952 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
951 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); 953 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
952 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); 954 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
953 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); 955 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
954 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); 956 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
955 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); 957 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
956 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); 958 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
957 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); 959 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
958 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); 960 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
959 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); 961 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
960 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); 962 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
961 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); 963 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
962 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); 964 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
963 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); 965 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
964 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); 966 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
965 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); 967 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
966 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); 968 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
967 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); 969 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
968 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); 970 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
969 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); 971 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
970 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); 972 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
971 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); 973 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
972 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); 974 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
973 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); 975 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
974 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); 976 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
975 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); 977 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
976 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); 978 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
977 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); 979 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
978 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); 980 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
979 981 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
980 ExecuteNonQuery(cmd); 982 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
983 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
984 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
985
986 ExecuteNonQuery(cmd);
987 }
981 } 988 }
982 } 989 }
983 } 990 }
984 991
985 public virtual void RemoveRegionWindlightSettings(UUID regionID) 992 public virtual void RemoveRegionWindlightSettings(UUID regionID)
986 { 993 {
987 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 994 lock (m_dbLock)
988 { 995 {
989 dbcon.Open(); 996 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
990
991 using (MySqlCommand cmd = dbcon.CreateCommand())
992 { 997 {
993 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID"; 998 dbcon.Open();
994 cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); 999
995 ExecuteNonQuery(cmd); 1000 using (MySqlCommand cmd = dbcon.CreateCommand())
1001 {
1002 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
1003 cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
1004 ExecuteNonQuery(cmd);
1005 }
996 } 1006 }
997 } 1007 }
998 } 1008 }
@@ -1000,26 +1010,29 @@ namespace OpenSim.Data.MySQL
1000 #region RegionEnvironmentSettings 1010 #region RegionEnvironmentSettings
1001 public string LoadRegionEnvironmentSettings(UUID regionUUID) 1011 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1002 { 1012 {
1003 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1013 lock (m_dbLock)
1004 { 1014 {
1005 dbcon.Open(); 1015 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1006
1007 string command = "select * from `regionenvironment` where region_id = ?region_id";
1008
1009 using (MySqlCommand cmd = new MySqlCommand(command))
1010 { 1016 {
1011 cmd.Connection = dbcon; 1017 dbcon.Open();
1012 1018
1013 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1019 string command = "select * from `regionenvironment` where region_id = ?region_id";
1014 1020
1015 IDataReader result = ExecuteReader(cmd); 1021 using (MySqlCommand cmd = new MySqlCommand(command))
1016 if (!result.Read())
1017 {
1018 return String.Empty;
1019 }
1020 else
1021 { 1022 {
1022 return Convert.ToString(result["llsd_settings"]); 1023 cmd.Connection = dbcon;
1024
1025 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1026
1027 IDataReader result = ExecuteReader(cmd);
1028 if (!result.Read())
1029 {
1030 return String.Empty;
1031 }
1032 else
1033 {
1034 return Convert.ToString(result["llsd_settings"]);
1035 }
1023 } 1036 }
1024 } 1037 }
1025 } 1038 }
@@ -1027,33 +1040,39 @@ namespace OpenSim.Data.MySQL
1027 1040
1028 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 1041 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1029 { 1042 {
1030 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1043 lock (m_dbLock)
1031 { 1044 {
1032 dbcon.Open(); 1045 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1033
1034 using (MySqlCommand cmd = dbcon.CreateCommand())
1035 { 1046 {
1036 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; 1047 dbcon.Open();
1037 1048
1038 cmd.Parameters.AddWithValue("region_id", regionUUID); 1049 using (MySqlCommand cmd = dbcon.CreateCommand())
1039 cmd.Parameters.AddWithValue("llsd_settings", settings); 1050 {
1040 1051 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
1041 ExecuteNonQuery(cmd); 1052
1053 cmd.Parameters.AddWithValue("region_id", regionUUID);
1054 cmd.Parameters.AddWithValue("llsd_settings", settings);
1055
1056 ExecuteNonQuery(cmd);
1057 }
1042 } 1058 }
1043 } 1059 }
1044 } 1060 }
1045 1061
1046 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 1062 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1047 { 1063 {
1048 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1064 lock (m_dbLock)
1049 { 1065 {
1050 dbcon.Open(); 1066 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1051
1052 using (MySqlCommand cmd = dbcon.CreateCommand())
1053 { 1067 {
1054 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id"; 1068 dbcon.Open();
1055 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1069
1056 ExecuteNonQuery(cmd); 1070 using (MySqlCommand cmd = dbcon.CreateCommand())
1071 {
1072 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
1073 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1074 ExecuteNonQuery(cmd);
1075 }
1057 } 1076 }
1058 } 1077 }
1059 } 1078 }
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs
index 79e20fc..31cab4a 100644
--- a/OpenSim/Framework/Cache.cs
+++ b/OpenSim/Framework/Cache.cs
@@ -199,7 +199,14 @@ namespace OpenSim.Framework
199 // 199 //
200 public class Cache 200 public class Cache
201 { 201 {
202 /// <summary>
203 /// Must only be accessed under lock.
204 /// </summary>
202 private List<CacheItemBase> m_Index = new List<CacheItemBase>(); 205 private List<CacheItemBase> m_Index = new List<CacheItemBase>();
206
207 /// <summary>
208 /// Must only be accessed under m_Index lock.
209 /// </summary>
203 private Dictionary<string, CacheItemBase> m_Lookup = 210 private Dictionary<string, CacheItemBase> m_Lookup =
204 new Dictionary<string, CacheItemBase>(); 211 new Dictionary<string, CacheItemBase>();
205 212
@@ -320,19 +327,19 @@ namespace OpenSim.Framework
320 { 327 {
321 if (m_Lookup.ContainsKey(index)) 328 if (m_Lookup.ContainsKey(index))
322 item = m_Lookup[index]; 329 item = m_Lookup[index];
323 }
324 330
325 if (item == null) 331 if (item == null)
326 { 332 {
333 Expire(true);
334 return null;
335 }
336
337 item.hits++;
338 item.lastUsed = DateTime.Now;
339
327 Expire(true); 340 Expire(true);
328 return null;
329 } 341 }
330 342
331 item.hits++;
332 item.lastUsed = DateTime.Now;
333
334 Expire(true);
335
336 return item; 343 return item;
337 } 344 }
338 345
@@ -385,7 +392,10 @@ namespace OpenSim.Framework
385 // 392 //
386 public Object Find(Predicate<CacheItemBase> d) 393 public Object Find(Predicate<CacheItemBase> d)
387 { 394 {
388 CacheItemBase item = m_Index.Find(d); 395 CacheItemBase item;
396
397 lock (m_Index)
398 item = m_Index.Find(d);
389 399
390 if (item == null) 400 if (item == null)
391 return null; 401 return null;
@@ -419,12 +429,12 @@ namespace OpenSim.Framework
419 public virtual void Store(string index, Object data, Type container, 429 public virtual void Store(string index, Object data, Type container,
420 Object[] parameters) 430 Object[] parameters)
421 { 431 {
422 Expire(false);
423
424 CacheItemBase item; 432 CacheItemBase item;
425 433
426 lock (m_Index) 434 lock (m_Index)
427 { 435 {
436 Expire(false);
437
428 if (m_Index.Contains(new CacheItemBase(index))) 438 if (m_Index.Contains(new CacheItemBase(index)))
429 { 439 {
430 if ((m_Flags & CacheFlags.AllowUpdate) != 0) 440 if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@@ -450,9 +460,17 @@ namespace OpenSim.Framework
450 m_Index.Add(item); 460 m_Index.Add(item);
451 m_Lookup[index] = item; 461 m_Lookup[index] = item;
452 } 462 }
463
453 item.Store(data); 464 item.Store(data);
454 } 465 }
455 466
467 /// <summary>
468 /// Expire items as appropriate.
469 /// </summary>
470 /// <remarks>
471 /// Callers must lock m_Index.
472 /// </remarks>
473 /// <param name='getting'></param>
456 protected virtual void Expire(bool getting) 474 protected virtual void Expire(bool getting)
457 { 475 {
458 if (getting && (m_Strategy == CacheStrategy.Aggressive)) 476 if (getting && (m_Strategy == CacheStrategy.Aggressive))
@@ -475,12 +493,10 @@ namespace OpenSim.Framework
475 493
476 switch (m_Strategy) 494 switch (m_Strategy)
477 { 495 {
478 case CacheStrategy.Aggressive: 496 case CacheStrategy.Aggressive:
479 if (Count < Size) 497 if (Count < Size)
480 return; 498 return;
481 499
482 lock (m_Index)
483 {
484 m_Index.Sort(new SortLRU()); 500 m_Index.Sort(new SortLRU());
485 m_Index.Reverse(); 501 m_Index.Reverse();
486 502
@@ -490,7 +506,7 @@ namespace OpenSim.Framework
490 506
491 ExpireDelegate doExpire = OnExpire; 507 ExpireDelegate doExpire = OnExpire;
492 508
493 if (doExpire != null) 509 if (doExpire != null)
494 { 510 {
495 List<CacheItemBase> candidates = 511 List<CacheItemBase> candidates =
496 m_Index.GetRange(target, Count - target); 512 m_Index.GetRange(target, Count - target);
@@ -513,27 +529,34 @@ namespace OpenSim.Framework
513 foreach (CacheItemBase item in m_Index) 529 foreach (CacheItemBase item in m_Index)
514 m_Lookup[item.uuid] = item; 530 m_Lookup[item.uuid] = item;
515 } 531 }
516 } 532
517 break; 533 break;
518 default: 534
519 break; 535 default:
536 break;
520 } 537 }
521 } 538 }
522 539
523 public void Invalidate(string uuid) 540 public void Invalidate(string uuid)
524 { 541 {
525 if (!m_Lookup.ContainsKey(uuid)) 542 lock (m_Index)
526 return; 543 {
544 if (!m_Lookup.ContainsKey(uuid))
545 return;
527 546
528 CacheItemBase item = m_Lookup[uuid]; 547 CacheItemBase item = m_Lookup[uuid];
529 m_Lookup.Remove(uuid); 548 m_Lookup.Remove(uuid);
530 m_Index.Remove(item); 549 m_Index.Remove(item);
550 }
531 } 551 }
532 552
533 public void Clear() 553 public void Clear()
534 { 554 {
535 m_Index.Clear(); 555 lock (m_Index)
536 m_Lookup.Clear(); 556 {
557 m_Index.Clear();
558 m_Lookup.Clear();
559 }
537 } 560 }
538 } 561 }
539} 562} \ No newline at end of file
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index 1b1aaf2..a2eb5ee 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Framework
31 public class Constants 31 public class Constants
32 { 32 {
33 public const uint RegionSize = 256; 33 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096;
34 public const byte TerrainPatchSize = 16; 35 public const byte TerrainPatchSize = 16;
35 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
36 37
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 6be2bd7..91f36a5 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1046,8 +1046,21 @@ namespace OpenSim.Framework
1046 1046
1047 void InPacket(object NewPack); 1047 void InPacket(object NewPack);
1048 void ProcessInPacket(Packet NewPack); 1048 void ProcessInPacket(Packet NewPack);
1049
1050 /// <summary>
1051 /// Close this client
1052 /// </summary>
1049 void Close(); 1053 void Close();
1050 void Close(bool sendStop); 1054
1055 /// <summary>
1056 /// Close this client
1057 /// </summary>
1058 /// <param name='force'>
1059 /// If true, attempts the close without checking active status. You do not want to try this except as a last
1060 /// ditch attempt where Active == false but the ScenePresence still exists.
1061 /// </param>
1062 void Close(bool sendStop, bool force);
1063
1051 void Kick(string message); 1064 void Kick(string message);
1052 1065
1053 /// <summary> 1066 /// <summary>
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index a12183c..b3457a6 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -73,33 +73,27 @@ namespace OpenSim.Framework
73 { 73 {
74 } 74 }
75 75
76 public InventoryFolderBase(UUID id) 76 public InventoryFolderBase(UUID id) : this()
77 { 77 {
78 ID = id; 78 ID = id;
79 } 79 }
80 80
81 public InventoryFolderBase(UUID id, UUID owner) 81 public InventoryFolderBase(UUID id, UUID owner) : this(id)
82 { 82 {
83 ID = id;
84 Owner = owner; 83 Owner = owner;
85 } 84 }
86 85
87 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) 86 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
88 { 87 {
89 ID = id;
90 Name = name; 88 Name = name;
91 Owner = owner;
92 ParentID = parent; 89 ParentID = parent;
93 } 90 }
94 91
95 public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) 92 public InventoryFolderBase(
93 UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
96 { 94 {
97 ID = id;
98 Name = name;
99 Owner = owner;
100 Type = type; 95 Type = type;
101 ParentID = parent;
102 Version = version; 96 Version = version;
103 } 97 }
104 } 98 }
105} 99} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index b709baa..eaddb8c 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -89,6 +89,17 @@ namespace OpenSim.Framework.Monitoring
89 FirstTick = Environment.TickCount & Int32.MaxValue; 89 FirstTick = Environment.TickCount & Int32.MaxValue;
90 LastTick = FirstTick; 90 LastTick = FirstTick;
91 } 91 }
92
93 public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
94 {
95 Thread = previousTwi.Thread;
96 FirstTick = previousTwi.FirstTick;
97 LastTick = previousTwi.LastTick;
98 Timeout = previousTwi.Timeout;
99 IsTimedOut = previousTwi.IsTimedOut;
100 AlarmIfTimeout = previousTwi.AlarmIfTimeout;
101 AlarmMethod = previousTwi.AlarmMethod;
102 }
92 } 103 }
93 104
94 /// <summary> 105 /// <summary>
@@ -335,7 +346,9 @@ namespace OpenSim.Framework.Monitoring
335 if (callbackInfos == null) 346 if (callbackInfos == null)
336 callbackInfos = new List<ThreadWatchdogInfo>(); 347 callbackInfos = new List<ThreadWatchdogInfo>();
337 348
338 callbackInfos.Add(threadInfo); 349 // Send a copy of the watchdog info to prevent race conditions where the watchdog
350 // thread updates the monitoring info after an alarm has been sent out.
351 callbackInfos.Add(new ThreadWatchdogInfo(threadInfo));
339 } 352 }
340 } 353 }
341 } 354 }
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 4bde7be..da87b05 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -122,10 +122,13 @@ namespace OpenSim.Framework
122 public UUID lastMapUUID = UUID.Zero; 122 public UUID lastMapUUID = UUID.Zero;
123 public string lastMapRefresh = "0"; 123 public string lastMapRefresh = "0";
124 124
125 private float m_nonphysPrimMin = 0;
125 private int m_nonphysPrimMax = 0; 126 private int m_nonphysPrimMax = 0;
127 private float m_physPrimMin = 0;
126 private int m_physPrimMax = 0; 128 private int m_physPrimMax = 0;
127 private bool m_clampPrimSize = false; 129 private bool m_clampPrimSize = false;
128 private int m_objectCapacity = 0; 130 private int m_objectCapacity = 0;
131 private int m_linksetCapacity = 0;
129 private int m_agentCapacity = 0; 132 private int m_agentCapacity = 0;
130 private string m_regionType = String.Empty; 133 private string m_regionType = String.Empty;
131 private RegionLightShareData m_windlight = new RegionLightShareData(); 134 private RegionLightShareData m_windlight = new RegionLightShareData();
@@ -287,11 +290,21 @@ namespace OpenSim.Framework
287 set { m_windlight = value; } 290 set { m_windlight = value; }
288 } 291 }
289 292
293 public float NonphysPrimMin
294 {
295 get { return m_nonphysPrimMin; }
296 }
297
290 public int NonphysPrimMax 298 public int NonphysPrimMax
291 { 299 {
292 get { return m_nonphysPrimMax; } 300 get { return m_nonphysPrimMax; }
293 } 301 }
294 302
303 public float PhysPrimMin
304 {
305 get { return m_physPrimMin; }
306 }
307
295 public int PhysPrimMax 308 public int PhysPrimMax
296 { 309 {
297 get { return m_physPrimMax; } 310 get { return m_physPrimMax; }
@@ -307,6 +320,11 @@ namespace OpenSim.Framework
307 get { return m_objectCapacity; } 320 get { return m_objectCapacity; }
308 } 321 }
309 322
323 public int LinksetCapacity
324 {
325 get { return m_linksetCapacity; }
326 }
327
310 public int AgentCapacity 328 public int AgentCapacity
311 { 329 {
312 get { return m_agentCapacity; } 330 get { return m_agentCapacity; }
@@ -625,16 +643,31 @@ namespace OpenSim.Framework
625 m_regionType = config.GetString("RegionType", String.Empty); 643 m_regionType = config.GetString("RegionType", String.Empty);
626 allKeys.Remove("RegionType"); 644 allKeys.Remove("RegionType");
627 645
628 // Prim stuff 646 #region Prim stuff
629 // 647
648 m_nonphysPrimMin = config.GetFloat("NonphysicalPrimMin", 0);
649 allKeys.Remove("NonphysicalPrimMin");
650
630 m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); 651 m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0);
631 allKeys.Remove("NonphysicalPrimMax"); 652 allKeys.Remove("NonphysicalPrimMax");
653
654 m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
655 allKeys.Remove("PhysicalPrimMin");
656
632 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); 657 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
633 allKeys.Remove("PhysicalPrimMax"); 658 allKeys.Remove("PhysicalPrimMax");
659
634 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); 660 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
635 allKeys.Remove("ClampPrimSize"); 661 allKeys.Remove("ClampPrimSize");
662
636 m_objectCapacity = config.GetInt("MaxPrims", 15000); 663 m_objectCapacity = config.GetInt("MaxPrims", 15000);
637 allKeys.Remove("MaxPrims"); 664 allKeys.Remove("MaxPrims");
665
666 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
667 allKeys.Remove("LinksetPrims");
668
669 #endregion
670
638 m_agentCapacity = config.GetInt("MaxAgents", 100); 671 m_agentCapacity = config.GetInt("MaxAgents", 100);
639 allKeys.Remove("MaxAgents"); 672 allKeys.Remove("MaxAgents");
640 673
@@ -673,15 +706,26 @@ namespace OpenSim.Framework
673 706
674 config.Set("ExternalHostName", m_externalHostName); 707 config.Set("ExternalHostName", m_externalHostName);
675 708
709 if (m_nonphysPrimMin != 0)
710 config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
711
676 if (m_nonphysPrimMax != 0) 712 if (m_nonphysPrimMax != 0)
677 config.Set("NonphysicalPrimMax", m_nonphysPrimMax); 713 config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
714
715 if (m_physPrimMin != 0)
716 config.Set("PhysicalPrimMax", m_physPrimMin);
717
678 if (m_physPrimMax != 0) 718 if (m_physPrimMax != 0)
679 config.Set("PhysicalPrimMax", m_physPrimMax); 719 config.Set("PhysicalPrimMax", m_physPrimMax);
720
680 config.Set("ClampPrimSize", m_clampPrimSize.ToString()); 721 config.Set("ClampPrimSize", m_clampPrimSize.ToString());
681 722
682 if (m_objectCapacity != 0) 723 if (m_objectCapacity != 0)
683 config.Set("MaxPrims", m_objectCapacity); 724 config.Set("MaxPrims", m_objectCapacity);
684 725
726 if (m_linksetCapacity != 0)
727 config.Set("LinksetPrims", m_linksetCapacity);
728
685 if (m_agentCapacity != 0) 729 if (m_agentCapacity != 0)
686 config.Set("MaxAgents", m_agentCapacity); 730 config.Set("MaxAgents", m_agentCapacity);
687 731
@@ -759,9 +803,15 @@ namespace OpenSim.Framework
759 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 803 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
760 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); 804 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
761 805
806 configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
807 "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
808
762 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 809 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
763 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); 810 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
764 811
812 configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
813 "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
814
765 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 815 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
766 "Maximum size for physical prims", m_physPrimMax.ToString(), true); 816 "Maximum size for physical prims", m_physPrimMax.ToString(), true);
767 817
@@ -771,6 +821,9 @@ namespace OpenSim.Framework
771 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 821 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
772 "Max objects this sim will hold", m_objectCapacity.ToString(), true); 822 "Max objects this sim will hold", m_objectCapacity.ToString(), true);
773 823
824 configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
825 "Max prims an object will hold", m_linksetCapacity.ToString(), true);
826
774 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 827 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
775 "Max avatars this sim will hold", m_agentCapacity.ToString(), true); 828 "Max avatars this sim will hold", m_agentCapacity.ToString(), true);
776 829
@@ -892,6 +945,9 @@ namespace OpenSim.Framework
892 case "object_capacity": 945 case "object_capacity":
893 m_objectCapacity = (int)configuration_result; 946 m_objectCapacity = (int)configuration_result;
894 break; 947 break;
948 case "linkset_capacity":
949 m_linksetCapacity = (int)configuration_result;
950 break;
895 case "agent_capacity": 951 case "agent_capacity":
896 m_agentCapacity = (int)configuration_result; 952 m_agentCapacity = (int)configuration_result;
897 break; 953 break;
diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs
index d31d27c..fa7160f 100644
--- a/OpenSim/Framework/Serialization/External/OspResolver.cs
+++ b/OpenSim/Framework/Serialization/External/OspResolver.cs
@@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
65 65
66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId); 66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
67 if (account != null) 67 if (account != null)
68 {
68 return MakeOspa(account.FirstName, account.LastName); 69 return MakeOspa(account.FirstName, account.LastName);
70 }
69// else 71// else
72// {
70// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); 73// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
74// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
75// }
71 76
72 return null; 77 return null;
73 } 78 }
@@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
79 /// <returns></returns> 84 /// <returns></returns>
80 public static string MakeOspa(string firstName, string lastName) 85 public static string MakeOspa(string firstName, string lastName)
81 { 86 {
82// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); 87 string ospa
88 = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
89
90// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
91// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
83 92
84 return 93 return ospa;
85 OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
86 } 94 }
87 95
88 /// <summary> 96 /// <summary>
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 016a174..bb094ed 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.4CM"; 32 private const string VERSION_NUMBER = "0.7.5CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 384f716..1a383ae 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -862,6 +862,12 @@ namespace OpenSim.Framework
862 return Math.Min(Math.Max(x, min), max); 862 return Math.Min(Math.Max(x, min), max);
863 } 863 }
864 864
865 public static Vector3 Clip(Vector3 vec, float min, float max)
866 {
867 return new Vector3(Clip(vec.X, min, max), Clip(vec.Y, min, max),
868 Clip(vec.Z, min, max));
869 }
870
865 /// <summary> 871 /// <summary>
866 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. 872 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
867 /// </summary> 873 /// </summary>
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6255515..9c7598a 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -35,6 +35,7 @@ using System.Text;
35using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers; 36using System.Timers;
37using log4net; 37using log4net;
38using NDesk.Options;
38using Nini.Config; 39using Nini.Config;
39using OpenMetaverse; 40using OpenMetaverse;
40using OpenSim.Framework; 41using OpenSim.Framework;
@@ -310,8 +311,11 @@ namespace OpenSim
310 "Change the scale of a named prim", HandleEditScale); 311 "Change the scale of a named prim", HandleEditScale);
311 312
312 m_console.Commands.AddCommand("Users", false, "kick user", 313 m_console.Commands.AddCommand("Users", false, "kick user",
313 "kick user <first> <last> [message]", 314 "kick user <first> <last> [--force] [message]",
314 "Kick a user off the simulator", KickUserCommand); 315 "Kick a user off the simulator",
316 "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
317 + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
318 KickUserCommand);
315 319
316 m_console.Commands.AddCommand("Users", false, "show users", 320 m_console.Commands.AddCommand("Users", false, "show users",
317 "show users [full]", 321 "show users [full]",
@@ -416,6 +420,7 @@ namespace OpenSim
416 { 420 {
417 RunCommandScript(m_shutdownCommandsFile); 421 RunCommandScript(m_shutdownCommandsFile);
418 } 422 }
423
419 base.ShutdownSpecific(); 424 base.ShutdownSpecific();
420 } 425 }
421 426
@@ -453,11 +458,17 @@ namespace OpenSim
453 /// <param name="cmdparams">name of avatar to kick</param> 458 /// <param name="cmdparams">name of avatar to kick</param>
454 private void KickUserCommand(string module, string[] cmdparams) 459 private void KickUserCommand(string module, string[] cmdparams)
455 { 460 {
456 if (cmdparams.Length < 4) 461 bool force = false;
462
463 OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
464
465 List<string> mainParams = options.Parse(cmdparams);
466
467 if (mainParams.Count < 4)
457 return; 468 return;
458 469
459 string alert = null; 470 string alert = null;
460 if (cmdparams.Length > 4) 471 if (mainParams.Count > 4)
461 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 472 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
462 473
463 IList agents = SceneManager.GetCurrentSceneAvatars(); 474 IList agents = SceneManager.GetCurrentSceneAvatars();
@@ -466,8 +477,8 @@ namespace OpenSim
466 { 477 {
467 RegionInfo regionInfo = presence.Scene.RegionInfo; 478 RegionInfo regionInfo = presence.Scene.RegionInfo;
468 479
469 if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && 480 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
470 presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) 481 presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
471 { 482 {
472 MainConsole.Instance.Output( 483 MainConsole.Instance.Output(
473 String.Format( 484 String.Format(
@@ -480,7 +491,7 @@ namespace OpenSim
480 else 491 else
481 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 492 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
482 493
483 presence.Scene.IncomingCloseAgent(presence.UUID); 494 presence.Scene.IncomingCloseAgent(presence.UUID, force);
484 } 495 }
485 } 496 }
486 497
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId); 97 m_scene.IncomingCloseAgent(spId, false);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 7749ef3..74b27d7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -509,19 +509,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 /// </summary> 509 /// </summary>
510 public void Close() 510 public void Close()
511 { 511 {
512 Close(true); 512 Close(true, false);
513 } 513 }
514 514
515 /// <summary> 515 public void Close(bool sendStop, bool force)
516 /// Shut down the client view
517 /// </summary>
518 public void Close(bool sendStop)
519 { 516 {
520 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 517 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
521 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 518 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
522 lock (CloseSyncLock) 519 lock (CloseSyncLock)
523 { 520 {
524 if (!IsActive) 521 // We still perform a force close inside the sync lock since this is intended to attempt close where
522 // there is some unidentified connection problem, not where we have issues due to deadlock
523 if (!IsActive && !force)
525 return; 524 return;
526 525
527 IsActive = false; 526 IsActive = false;
@@ -4528,7 +4527,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4528 { 4527 {
4529 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4528 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4530 } 4529 }
4531 j = 0; 4530 j = 0;
4532 4531
4533 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4532 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4534 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4533 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -12187,7 +12186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12187 { 12186 {
12188 Kick(reason); 12187 Kick(reason);
12189 Thread.Sleep(1000); 12188 Thread.Sleep(1000);
12190 Close(); 12189 Disconnect();
12191 } 12190 }
12192 12191
12193 public void Disconnect() 12192 public void Disconnect()
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index d6513c5..60ab70e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1523,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1523 if (!client.IsLoggingOut)
1524 { 1524 {
1525 client.IsLoggingOut = true; 1525 client.IsLoggingOut = true;
1526 client.Close(false); 1526 client.Close(false, false);
1527 } 1527 }
1528 } 1528 }
1529 } 1529 }
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d7176f..e1d4d78 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces;
52[assembly: Addin("FlotsamAssetCache", "1.1")] 52[assembly: Addin("FlotsamAssetCache", "1.1")]
53[assembly: AddinDependency("OpenSim", "0.5")] 53[assembly: AddinDependency("OpenSim", "0.5")]
54 54
55namespace Flotsam.RegionModules.AssetCache 55namespace OpenSim.Region.CoreModules.Asset
56{ 56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService 58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index c91b25f..1c2bfd0 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,7 +35,6 @@ using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
39using OpenSim.Framework; 38using OpenSim.Framework;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Scenes.Serialization; 40using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index d9a619d..48f3a23 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
461 461
462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
463 463
464 scene.IncomingCloseAgent(presence.UUID); 464 scene.IncomingCloseAgent(presence.UUID, false);
465 465
466 // Check that we can't retrieve this attachment from the scene. 466 // Check that we can't retrieve this attachment from the scene.
467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index b112b6d..12a05b3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
351 } 351 }
352 352
353 /// <summary> 353// /// <summary>
354 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 354// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
355 /// an account exists with the same name as the creator, though not the same id. 355// /// an account exists with the same name as the creator, though not the same id.
356 /// </summary> 356// /// </summary>
357 [Test] 357// [Test]
358 public void TestLoadIarV0_1SameNameCreator() 358// public void TestLoadIarV0_1SameNameCreator()
359 { 359// {
360 TestHelpers.InMethod(); 360// TestHelpers.InMethod();
361// log4net.Config.XmlConfigurator.Configure(); 361// TestHelpers.EnableLogging();
362 362//
363 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 363// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
364 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 364// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
365 365//
366 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 366// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
367 InventoryItemBase foundItem1 367// InventoryItemBase foundItem1
368 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 368// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
369 369//
370 Assert.That( 370// Assert.That(
371 foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 371// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
372 "Loaded item non-uuid creator doesn't match original"); 372// "Loaded item non-uuid creator doesn't match original");
373 Assert.That( 373// Assert.That(
374 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 374// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
375 "Loaded item uuid creator doesn't match original"); 375// "Loaded item uuid creator doesn't match original");
376 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 376// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
377 "Loaded item owner doesn't match inventory reciever"); 377// "Loaded item owner doesn't match inventory reciever");
378 378//
379 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 379// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
380 string xmlData = Utils.BytesToString(asset1.Data); 380// string xmlData = Utils.BytesToString(asset1.Data);
381 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 381// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
382 382//
383 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 383// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
384 } 384// }
385 385
386 /// <summary> 386 /// <summary>
387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 9090f64..486f9d2 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -650,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
650 // an agent cannot teleport back to this region if it has teleported away. 650 // an agent cannot teleport back to this region if it has teleported away.
651 Thread.Sleep(2000); 651 Thread.Sleep(2000);
652 652
653 sp.Scene.IncomingCloseAgent(sp.UUID); 653 sp.Scene.IncomingCloseAgent(sp.UUID, false);
654 } 654 }
655 else 655 else
656 { 656 {
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
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.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 18bd018..1f340df 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,13 +42,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int ALL_SIDES = -1; 47 private const int ALL_SIDES = -1;
48 48
49 public const int DISP_EXPIRE = 1; 49 public const int DISP_EXPIRE = 1;
50 public const int DISP_TEMP = 2; 50 public const int DISP_TEMP = 2;
51 51
52 /// <summary>
53 /// If true then where possible dynamic textures are reused.
54 /// </summary>
55 public bool ReuseTextures { get; set; }
56
57 /// <summary>
58 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
59 /// </summary>
60 /// <remarks>
61 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
62 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
63 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
64 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
65 /// to work around this problem.</remarks>
66 public bool ReuseLowDataTextures { get; set; }
67
52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 68 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
53 69
54 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 70 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -56,6 +72,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
56 72
57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 73 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
58 74
75 /// <summary>
76 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
77 /// regenerate.
78 /// </summary>
79 /// <remarks>
80 /// Key is string.Format("{0}{1}", data
81 /// </remarks>
82 private Cache m_reuseableDynamicTextures;
83
59 #region IDynamicTextureManager Members 84 #region IDynamicTextureManager Members
60 85
61 public void RegisterRender(string handleType, IDynamicTextureRender render) 86 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -69,17 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
69 /// <summary> 94 /// <summary>
70 /// Called by code which actually renders the dynamic texture to supply texture data. 95 /// Called by code which actually renders the dynamic texture to supply texture data.
71 /// </summary> 96 /// </summary>
72 /// <param name="id"></param> 97 /// <param name="updaterId"></param>
73 /// <param name="data"></param> 98 /// <param name="texture"></param>
74 public void ReturnData(UUID id, byte[] data) 99 public void ReturnData(UUID updaterId, IDynamicTexture texture)
75 { 100 {
76 DynamicTextureUpdater updater = null; 101 DynamicTextureUpdater updater = null;
77 102
78 lock (Updaters) 103 lock (Updaters)
79 { 104 {
80 if (Updaters.ContainsKey(id)) 105 if (Updaters.ContainsKey(updaterId))
81 { 106 {
82 updater = Updaters[id]; 107 updater = Updaters[updaterId];
83 } 108 }
84 } 109 }
85 110
@@ -88,7 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
88 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 113 if (RegisteredScenes.ContainsKey(updater.SimUUID))
89 { 114 {
90 Scene scene = RegisteredScenes[updater.SimUUID]; 115 Scene scene = RegisteredScenes[updater.SimUUID];
91 updater.DataReceived(data, scene); 116 UUID newTextureID = updater.DataReceived(texture.Data, scene);
117
118 if (ReuseTextures
119 && !updater.BlendWithOldTexture
120 && texture.IsReuseable
121 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
122 {
123 m_reuseableDynamicTextures.Store(
124 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
125 }
92 } 126 }
93 } 127 }
94 128
@@ -104,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
104 } 138 }
105 } 139 }
106 140
141 /// <summary>
142 /// Determines whether the texture is reuseable based on its data size.
143 /// </summary>
144 /// <remarks>
145 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
146 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
147 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
148 /// </remarks>
149 /// <returns></returns>
150 private bool IsDataSizeReuseable(IDynamicTexture texture)
151 {
152// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
153 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
154
155// m_log.DebugFormat(
156// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
157// discardLevel2DataThreshold, texture.Data.Length);
158
159 return discardLevel2DataThreshold < texture.Data.Length;
160 }
161
107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 162 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
108 string extraParams, int updateTimer) 163 string extraParams, int updateTimer)
109 { 164 {
@@ -167,22 +222,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 222 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 223 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
169 { 224 {
170 if (RenderPlugins.ContainsKey(contentType)) 225 if (!RenderPlugins.ContainsKey(contentType))
226 return UUID.Zero;
227
228 Scene scene;
229 RegisteredScenes.TryGetValue(simID, out scene);
230
231 if (scene == null)
232 return UUID.Zero;
233
234 SceneObjectPart part = scene.GetSceneObjectPart(primID);
235
236 if (part == null)
237 return UUID.Zero;
238
239 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
240 // them.
241 if (ReuseTextures)
242 disp = disp & ~DISP_EXPIRE;
243
244 DynamicTextureUpdater updater = new DynamicTextureUpdater();
245 updater.SimUUID = simID;
246 updater.PrimID = primID;
247 updater.ContentType = contentType;
248 updater.BodyData = data;
249 updater.UpdateTimer = updateTimer;
250 updater.UpdaterID = UUID.Random();
251 updater.Params = extraParams;
252 updater.BlendWithOldTexture = SetBlending;
253 updater.FrontAlpha = AlphaValue;
254 updater.Face = face;
255 updater.Url = "Local image";
256 updater.Disp = disp;
257
258 object objReusableTextureUUID = null;
259
260 if (ReuseTextures && !updater.BlendWithOldTexture)
171 { 261 {
172 DynamicTextureUpdater updater = new DynamicTextureUpdater(); 262 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
173 updater.SimUUID = simID; 263 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
174 updater.PrimID = primID; 264
175 updater.ContentType = contentType; 265 if (objReusableTextureUUID != null)
176 updater.BodyData = data; 266 {
177 updater.UpdateTimer = updateTimer; 267 // If something else has removed this temporary asset from the cache, detect and invalidate
178 updater.UpdaterID = UUID.Random(); 268 // our cached uuid.
179 updater.Params = extraParams; 269 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
180 updater.BlendWithOldTexture = SetBlending; 270 {
181 updater.FrontAlpha = AlphaValue; 271 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
182 updater.Face = face; 272 objReusableTextureUUID = null;
183 updater.Url = "Local image"; 273 }
184 updater.Disp = disp; 274 }
275 }
185 276
277 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
278 if (objReusableTextureUUID == null)
279 {
186 lock (Updaters) 280 lock (Updaters)
187 { 281 {
188 if (!Updaters.ContainsKey(updater.UpdaterID)) 282 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -191,11 +285,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
191 } 285 }
192 } 286 }
193 287
288// m_log.DebugFormat(
289// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
290// part.Name, part.ParentGroup.Scene.Name);
291
194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 292 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
196 } 293 }
197 294 else
198 return UUID.Zero; 295 {
296// m_log.DebugFormat(
297// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
298// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
299
300 // No need to add to updaters as the texture is always the same. Not that this functionality
301 // apppears to be implemented anyway.
302 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
303 }
304
305 return updater.UpdaterID;
306 }
307
308 private string GenerateReusableTextureKey(string data, string extraParams)
309 {
310 return string.Format("{0}{1}", data, extraParams);
199 } 311 }
200 312
201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 313 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -215,6 +327,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
215 327
216 public void Initialise(Scene scene, IConfigSource config) 328 public void Initialise(Scene scene, IConfigSource config)
217 { 329 {
330 IConfig texturesConfig = config.Configs["Textures"];
331 if (texturesConfig != null)
332 {
333 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
334 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
335 }
336
218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 337 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
219 { 338 {
220 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); 339 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
@@ -224,6 +343,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
224 343
225 public void PostInitialise() 344 public void PostInitialise()
226 { 345 {
346 if (ReuseTextures)
347 {
348 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
349 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
350 }
227 } 351 }
228 352
229 public void Close() 353 public void Close()
@@ -269,9 +393,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
269 } 393 }
270 394
271 /// <summary> 395 /// <summary>
396 /// Update the given part with the new texture.
397 /// </summary>
398 /// <returns>
399 /// The old texture UUID.
400 /// </returns>
401 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
402 {
403 UUID oldID;
404
405 lock (part)
406 {
407 // mostly keep the values from before
408 Primitive.TextureEntry tmptex = part.Shape.Textures;
409
410 // FIXME: Need to return the appropriate ID if only a single face is replaced.
411 oldID = tmptex.DefaultTexture.TextureID;
412
413 if (Face == ALL_SIDES)
414 {
415 oldID = tmptex.DefaultTexture.TextureID;
416 tmptex.DefaultTexture.TextureID = textureID;
417 }
418 else
419 {
420 try
421 {
422 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
423 texface.TextureID = textureID;
424 tmptex.FaceTextures[Face] = texface;
425 }
426 catch (Exception)
427 {
428 tmptex.DefaultTexture.TextureID = textureID;
429 }
430 }
431
432 // I'm pretty sure we always want to force this to true
433 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
434 // tmptex.DefaultTexture.Fullbright = true;
435
436 part.UpdateTextureEntry(tmptex.GetBytes());
437 }
438
439 return oldID;
440 }
441
442 /// <summary>
272 /// Called once new texture data has been received for this updater. 443 /// Called once new texture data has been received for this updater.
273 /// </summary> 444 /// </summary>
274 public void DataReceived(byte[] data, Scene scene) 445 /// <param name="data"></param>
446 /// <param name="scene"></param>
447 /// <param name="isReuseable">True if the data given is reuseable.</param>
448 /// <returns>The asset UUID given to the incoming data.</returns>
449 public UUID DataReceived(byte[] data, Scene scene)
275 { 450 {
276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 451 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
277 452
@@ -281,7 +456,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 456 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 457 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 458 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
284 return; 459
460 return UUID.Zero;
285 } 461 }
286 462
287 byte[] assetData = null; 463 byte[] assetData = null;
@@ -319,56 +495,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 495 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
320 if (cacheLayerDecode != null) 496 if (cacheLayerDecode != null)
321 { 497 {
322 cacheLayerDecode.Decode(asset.FullID, asset.Data); 498 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
323 cacheLayerDecode = null; 499 m_log.WarnFormat(
500 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
501 asset.ID, part.Name, part.ParentGroup.Scene.Name);
324 } 502 }
325 503
326 UUID oldID = UUID.Zero; 504 UUID oldID = UpdatePart(part, asset.FullID);
327
328 lock (part)
329 {
330 // mostly keep the values from before
331 Primitive.TextureEntry tmptex = part.Shape.Textures;
332
333 // remove the old asset from the cache
334 oldID = tmptex.DefaultTexture.TextureID;
335
336 if (Face == ALL_SIDES)
337 {
338 tmptex.DefaultTexture.TextureID = asset.FullID;
339 }
340 else
341 {
342 try
343 {
344 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
345 texface.TextureID = asset.FullID;
346 tmptex.FaceTextures[Face] = texface;
347 }
348 catch (Exception)
349 {
350 tmptex.DefaultTexture.TextureID = asset.FullID;
351 }
352 }
353
354 // I'm pretty sure we always want to force this to true
355 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
356 // tmptex.DefaultTexture.Fullbright = true;
357
358 part.UpdateTextureEntry(tmptex.GetBytes());
359 }
360 505
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 506 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 { 507 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); 508 if (oldAsset == null)
509 oldAsset = scene.AssetService.Get(oldID.ToString());
510
364 if (oldAsset != null) 511 if (oldAsset != null)
365 { 512 {
366 if (oldAsset.Temporary == true) 513 if (oldAsset.Temporary)
367 { 514 {
368 scene.AssetService.Delete(oldID.ToString()); 515 scene.AssetService.Delete(oldID.ToString());
369 } 516 }
370 } 517 }
371 } 518 }
519
520 return asset.FullID;
372 } 521 }
373 522
374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 523 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 13762f7..99ffbe7 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -58,6 +58,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
58 public string body; 58 public string body;
59 public int responseCode; 59 public int responseCode;
60 public string responseBody; 60 public string responseBody;
61 public string responseType = "text/plain";
61 //public ManualResetEvent ev; 62 //public ManualResetEvent ev;
62 public bool requestDone; 63 public bool requestDone;
63 public int startTime; 64 public int startTime;
@@ -270,6 +271,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
270 } 271 }
271 } 272 }
272 273
274 public void HttpContentType(UUID request, string type)
275 {
276 lock (m_UrlMap)
277 {
278 if (m_RequestMap.ContainsKey(request))
279 {
280 UrlData urlData = m_RequestMap[request];
281 urlData.requests[request].responseType = type;
282 }
283 else
284 {
285 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
286 }
287 }
288 }
289
273 public void HttpResponse(UUID request, int status, string body) 290 public void HttpResponse(UUID request, int status, string body)
274 { 291 {
275 lock (m_RequestMap) 292 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f83948..45e6527 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,6 +32,7 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using log4net; 38using log4net;
@@ -67,12 +68,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
67 return true; 68 return true;
68 } 69 }
69 70
70 public byte[] ConvertUrl(string url, string extraParams) 71// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
72// {
73// // We don't support conversion of body data.
74// return false;
75// }
76
77 public IDynamicTexture ConvertUrl(string url, string extraParams)
71 { 78 {
72 return null; 79 return null;
73 } 80 }
74 81
75 public byte[] ConvertStream(Stream data, string extraParams) 82 public IDynamicTexture ConvertData(string bodyData, string extraParams)
76 { 83 {
77 return null; 84 return null;
78 } 85 }
@@ -165,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
165 172
166 private void HttpRequestReturn(IAsyncResult result) 173 private void HttpRequestReturn(IAsyncResult result)
167 { 174 {
168
169 RequestState state = (RequestState) result.AsyncState; 175 RequestState state = (RequestState) result.AsyncState;
170 WebRequest request = (WebRequest) state.Request; 176 WebRequest request = (WebRequest) state.Request;
171 Stream stream = null; 177 Stream stream = null;
172 byte[] imageJ2000 = new byte[0]; 178 byte[] imageJ2000 = new byte[0];
179 Size newSize = new Size(0, 0);
173 180
174 try 181 try
175 { 182 {
@@ -182,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
182 try 189 try
183 { 190 {
184 Bitmap image = new Bitmap(stream); 191 Bitmap image = new Bitmap(stream);
185 Size newsize;
186 192
187 // TODO: make this a bit less hard coded 193 // TODO: make this a bit less hard coded
188 if ((image.Height < 64) && (image.Width < 64)) 194 if ((image.Height < 64) && (image.Width < 64))
189 { 195 {
190 newsize = new Size(32, 32); 196 newSize.Width = 32;
197 newSize.Height = 32;
191 } 198 }
192 else if ((image.Height < 128) && (image.Width < 128)) 199 else if ((image.Height < 128) && (image.Width < 128))
193 { 200 {
194 newsize = new Size(64, 64); 201 newSize.Width = 64;
202 newSize.Height = 64;
195 } 203 }
196 else if ((image.Height < 256) && (image.Width < 256)) 204 else if ((image.Height < 256) && (image.Width < 256))
197 { 205 {
198 newsize = new Size(128, 128); 206 newSize.Width = 128;
207 newSize.Height = 128;
199 } 208 }
200 else if ((image.Height < 512 && image.Width < 512)) 209 else if ((image.Height < 512 && image.Width < 512))
201 { 210 {
202 newsize = new Size(256, 256); 211 newSize.Width = 256;
212 newSize.Height = 256;
203 } 213 }
204 else if ((image.Height < 1024 && image.Width < 1024)) 214 else if ((image.Height < 1024 && image.Width < 1024))
205 { 215 {
206 newsize = new Size(512, 512); 216 newSize.Width = 512;
217 newSize.Height = 512;
207 } 218 }
208 else 219 else
209 { 220 {
210 newsize = new Size(1024, 1024); 221 newSize.Width = 1024;
222 newSize.Height = 1024;
211 } 223 }
212 224
213 Bitmap resize = new Bitmap(image, newsize); 225 using (Bitmap resize = new Bitmap(image, newSize))
214 226 {
215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 227 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
228 }
216 } 229 }
217 catch (Exception) 230 catch (Exception)
218 { 231 {
@@ -227,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
227 } 240 }
228 catch (WebException) 241 catch (WebException)
229 { 242 {
230
231 } 243 }
232 finally 244 finally
233 { 245 {
@@ -236,9 +248,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
236 stream.Close(); 248 stream.Close();
237 } 249 }
238 } 250 }
239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", 251
252 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
240 imageJ2000.Length, state.RequestID); 253 imageJ2000.Length, state.RequestID);
241 m_textureManager.ReturnData(state.RequestID, imageJ2000); 254
255 m_textureManager.ReturnData(
256 state.RequestID,
257 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
258 request.RequestUri, null, imageJ2000, newSize, false));
242 } 259 }
243 260
244 #region Nested type: RequestState 261 #region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c..41baccc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,292 @@ using OpenSim.Tests.Common.Mock;
45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
46{ 46{
47 [TestFixture] 47 [TestFixture]
48 public class VectorRenderModuleTests 48 public class VectorRenderModuleTests : OpenSimTestCase
49 { 49 {
50 Scene m_scene;
51 DynamicTextureModule m_dtm;
52 VectorRenderModule m_vrm;
53
54 private void SetupScene(bool reuseTextures)
55 {
56 m_scene = new SceneHelpers().SetupScene();
57
58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
61
62 m_vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
65 }
66
50 [Test] 67 [Test]
51 public void TestDraw() 68 public void TestDraw()
52 { 69 {
53 TestHelpers.InMethod(); 70 TestHelpers.InMethod();
54 71
55 Scene scene = new SceneHelpers().SetupScene(); 72 SetupScene(false);
56 DynamicTextureModule dtm = new DynamicTextureModule(); 73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
57 VectorRenderModule vrm = new VectorRenderModule();
58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
59
60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
62 75
63 dtm.AddDynamicTextureData( 76 m_dtm.AddDynamicTextureData(
64 scene.RegionInfo.RegionID, 77 m_scene.RegionInfo.RegionID,
65 so.UUID, 78 so.UUID,
66 vrm.GetContentType(), 79 m_vrm.GetContentType(),
67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
68 "", 81 "",
69 0); 82 0);
70 83
84 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
85 }
86
87 [Test]
88 public void TestRepeatSameDraw()
89 {
90 TestHelpers.InMethod();
91
92 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
93
94 SetupScene(false);
95 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
96
97 m_dtm.AddDynamicTextureData(
98 m_scene.RegionInfo.RegionID,
99 so.UUID,
100 m_vrm.GetContentType(),
101 dtText,
102 "",
103 0);
104
105 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
106
107 m_dtm.AddDynamicTextureData(
108 m_scene.RegionInfo.RegionID,
109 so.UUID,
110 m_vrm.GetContentType(),
111 dtText,
112 "",
113 0);
114
115 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
116 }
117
118 [Test]
119 public void TestRepeatSameDrawDifferentExtraParams()
120 {
121 TestHelpers.InMethod();
122
123 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
124
125 SetupScene(false);
126 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
127
128 m_dtm.AddDynamicTextureData(
129 m_scene.RegionInfo.RegionID,
130 so.UUID,
131 m_vrm.GetContentType(),
132 dtText,
133 "",
134 0);
135
136 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
137
138 m_dtm.AddDynamicTextureData(
139 m_scene.RegionInfo.RegionID,
140 so.UUID,
141 m_vrm.GetContentType(),
142 dtText,
143 "alpha:250",
144 0);
145
146 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
147 }
148
149 [Test]
150 public void TestRepeatSameDrawContainingImage()
151 {
152 TestHelpers.InMethod();
153
154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
156
157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
159
160 m_dtm.AddDynamicTextureData(
161 m_scene.RegionInfo.RegionID,
162 so.UUID,
163 m_vrm.GetContentType(),
164 dtText,
165 "",
166 0);
167
168 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
169
170 m_dtm.AddDynamicTextureData(
171 m_scene.RegionInfo.RegionID,
172 so.UUID,
173 m_vrm.GetContentType(),
174 dtText,
175 "",
176 0);
177
178 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
179 }
180
181 [Test]
182 public void TestDrawReusingTexture()
183 {
184 TestHelpers.InMethod();
185
186 SetupScene(true);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189
190 m_dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID,
192 so.UUID,
193 m_vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "",
196 0);
71 197
72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
73 } 199 }
200
201 [Test]
202 public void TestRepeatSameDrawReusingTexture()
203 {
204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
206
207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
208
209 SetupScene(true);
210 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
211
212 m_dtm.AddDynamicTextureData(
213 m_scene.RegionInfo.RegionID,
214 so.UUID,
215 m_vrm.GetContentType(),
216 dtText,
217 "",
218 0);
219
220 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
221
222 m_dtm.AddDynamicTextureData(
223 m_scene.RegionInfo.RegionID,
224 so.UUID,
225 m_vrm.GetContentType(),
226 dtText,
227 "",
228 0);
229
230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
231 }
232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
273 [Test]
274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
275 {
276 TestHelpers.InMethod();
277
278 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
279
280 SetupScene(true);
281 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
282
283 m_dtm.AddDynamicTextureData(
284 m_scene.RegionInfo.RegionID,
285 so.UUID,
286 m_vrm.GetContentType(),
287 dtText,
288 "",
289 0);
290
291 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
292
293 m_dtm.AddDynamicTextureData(
294 m_scene.RegionInfo.RegionID,
295 so.UUID,
296 m_vrm.GetContentType(),
297 dtText,
298 "alpha:250",
299 0);
300
301 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
302 }
303
304 [Test]
305 public void TestRepeatSameDrawContainingImageReusingTexture()
306 {
307 TestHelpers.InMethod();
308
309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
311
312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
314
315 m_dtm.AddDynamicTextureData(
316 m_scene.RegionInfo.RegionID,
317 so.UUID,
318 m_vrm.GetContentType(),
319 dtText,
320 "",
321 0);
322
323 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
324
325 m_dtm.AddDynamicTextureData(
326 m_scene.RegionInfo.RegionID,
327 so.UUID,
328 m_vrm.GetContentType(),
329 dtText,
330 "",
331 0);
332
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 }
74 } 335 }
75} \ No newline at end of file 336} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 8b2f2f8..1e17b02 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,10 +30,12 @@ using System.Drawing;
30using System.Drawing.Imaging; 30using System.Drawing.Imaging;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Linq;
33using System.Net; 34using System.Net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Imaging; 37using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
37using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using log4net; 41using log4net;
@@ -45,9 +47,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
45{ 47{
46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 48 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
47 { 49 {
50 // These fields exist for testing purposes, please do not remove.
51// private static bool s_flipper;
52// private static byte[] s_asset1Data;
53// private static byte[] s_asset2Data;
54
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 56
50 private string m_name = "VectorRenderModule";
51 private Scene m_scene; 57 private Scene m_scene;
52 private IDynamicTextureManager m_textureManager; 58 private IDynamicTextureManager m_textureManager;
53 private Graphics m_graph; 59 private Graphics m_graph;
@@ -61,12 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
61 67
62 public string GetContentType() 68 public string GetContentType()
63 { 69 {
64 return ("vector"); 70 return "vector";
65 } 71 }
66 72
67 public string GetName() 73 public string GetName()
68 { 74 {
69 return m_name; 75 return Name;
70 } 76 }
71 77
72 public bool SupportsAsynchronous() 78 public bool SupportsAsynchronous()
@@ -74,14 +80,20 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
74 return true; 80 return true;
75 } 81 }
76 82
77 public byte[] ConvertUrl(string url, string extraParams) 83// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
84// {
85// string[] lines = GetLines(bodyData);
86// return lines.Any((str, r) => str.StartsWith("Image"));
87// }
88
89 public IDynamicTexture ConvertUrl(string url, string extraParams)
78 { 90 {
79 return null; 91 return null;
80 } 92 }
81 93
82 public byte[] ConvertStream(Stream data, string extraParams) 94 public IDynamicTexture ConvertData(string bodyData, string extraParams)
83 { 95 {
84 return null; 96 return Draw(bodyData, extraParams);
85 } 97 }
86 98
87 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 99 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,7 +103,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
91 103
92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 104 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
93 { 105 {
94 Draw(bodyData, id, extraParams); 106 // XXX: This isn't actually being done asynchronously!
107 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
108
95 return true; 109 return true;
96 } 110 }
97 111
@@ -144,6 +158,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
144 { 158 {
145 m_textureManager.RegisterRender(GetContentType(), this); 159 m_textureManager.RegisterRender(GetContentType(), this);
146 } 160 }
161
162 // This code exists for testing purposes, please do not remove.
163// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
164// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
165
166 // Terrain dirt - smallest bin/assets file (6004 bytes)
167// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
147 } 168 }
148 169
149 public void Close() 170 public void Close()
@@ -152,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
152 173
153 public string Name 174 public string Name
154 { 175 {
155 get { return m_name; } 176 get { return "VectorRenderModule"; }
156 } 177 }
157 178
158 public bool IsSharedModule 179 public bool IsSharedModule
@@ -162,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
162 183
163 #endregion 184 #endregion
164 185
165 private void Draw(string data, UUID id, string extraParams) 186 private IDynamicTexture Draw(string data, string extraParams)
166 { 187 {
167 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 188 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 189 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -305,40 +326,57 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
305 326
306 Bitmap bitmap = null; 327 Bitmap bitmap = null;
307 Graphics graph = null; 328 Graphics graph = null;
329 bool reuseable = false;
308 330
309 try 331 try
310 { 332 {
311 if (alpha == 256) 333 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); 334 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
313 else 335 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 336 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
315 337 // under lock.
316 graph = Graphics.FromImage(bitmap); 338 lock (this)
317
318 // this is really just to save people filling the
319 // background color in their scripts, only do when fully opaque
320 if (alpha >= 255)
321 { 339 {
322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 340 if (alpha == 256)
341 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
342 else
343 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
344
345 graph = Graphics.FromImage(bitmap);
346
347 // this is really just to save people filling the
348 // background color in their scripts, only do when fully opaque
349 if (alpha >= 255)
323 { 350 {
324 graph.FillRectangle(bgFillBrush, 0, 0, width, height); 351 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
352 {
353 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
354 }
325 } 355 }
326 } 356
327 357 for (int w = 0; w < bitmap.Width; w++)
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
331 { 358 {
332 for (int h = 0; h < bitmap.Height; h++) 359 if (alpha <= 255)
333 { 360 {
334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); 361 for (int h = 0; h < bitmap.Height; h++)
362 {
363 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
364 }
335 } 365 }
336 } 366 }
367
368 GDIDraw(data, graph, altDataDelim, out reuseable);
337 } 369 }
338 370
339 GDIDraw(data, graph, altDataDelim);
340
341 byte[] imageJ2000 = new byte[0]; 371 byte[] imageJ2000 = new byte[0];
372
373 // This code exists for testing purposes, please do not remove.
374// if (s_flipper)
375// imageJ2000 = s_asset1Data;
376// else
377// imageJ2000 = s_asset2Data;
378//
379// s_flipper = !s_flipper;
342 380
343 try 381 try
344 { 382 {
@@ -351,15 +389,24 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
351 e.Message, e.StackTrace); 389 e.Message, e.StackTrace);
352 } 390 }
353 391
354 m_textureManager.ReturnData(id, imageJ2000); 392 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
393 data, extraParams, imageJ2000, new Size(width, height), reuseable);
355 } 394 }
356 finally 395 finally
357 { 396 {
358 if (graph != null) 397 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
359 graph.Dispose(); 398 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
360 399 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
361 if (bitmap != null) 400 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
362 bitmap.Dispose(); 401 // under lock.
402 lock (this)
403 {
404 if (graph != null)
405 graph.Dispose();
406
407 if (bitmap != null)
408 bitmap.Dispose();
409 }
363 } 410 }
364 } 411 }
365 412
@@ -418,8 +465,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
418 } 465 }
419*/ 466*/
420 467
421 private void GDIDraw(string data, Graphics graph, char dataDelim) 468 /// <summary>
469 /// Split input data into discrete command lines.
470 /// </summary>
471 /// <returns></returns>
472 /// <param name='data'></param>
473 /// <param name='dataDelim'></param>
474 private string[] GetLines(string data, char dataDelim)
475 {
476 char[] lineDelimiter = { dataDelim };
477 return data.Split(lineDelimiter);
478 }
479
480 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
422 { 481 {
482 reuseable = true;
423 Point startPoint = new Point(0, 0); 483 Point startPoint = new Point(0, 0);
424 Point endPoint = new Point(0, 0); 484 Point endPoint = new Point(0, 0);
425 Pen drawPen = null; 485 Pen drawPen = null;
@@ -434,11 +494,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
434 myFont = new Font(fontName, fontSize); 494 myFont = new Font(fontName, fontSize);
435 myBrush = new SolidBrush(Color.Black); 495 myBrush = new SolidBrush(Color.Black);
436 496
437 char[] lineDelimiter = {dataDelim};
438 char[] partsDelimiter = {','}; 497 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
440 498
441 foreach (string line in lines) 499 foreach (string line in GetLines(data, dataDelim))
442 { 500 {
443 string nextLine = line.Trim(); 501 string nextLine = line.Trim();
444 //replace with switch, or even better, do some proper parsing 502 //replace with switch, or even better, do some proper parsing
@@ -469,6 +527,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
469 } 527 }
470 else if (nextLine.StartsWith("Image")) 528 else if (nextLine.StartsWith("Image"))
471 { 529 {
530 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
531 // can change.
532 reuseable = false;
533
472 float x = 0; 534 float x = 0;
473 float y = 0; 535 float y = 0;
474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 536 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index b286d17..57ae549 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class GridConnectorsTests 46 public class GridConnectorsTests : OpenSimTestCase
47 { 47 {
48 LocalGridServicesConnector m_LocalConnector; 48 LocalGridServicesConnector m_LocalConnector;
49 private void SetUp() 49 private void SetUp()
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 6eb99ea..8ed1833 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -313,7 +313,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
313 313
314 if (m_scenes.ContainsKey(destination.RegionID)) 314 if (m_scenes.ContainsKey(destination.RegionID))
315 { 315 {
316 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); 316// m_log.DebugFormat(
317// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
318// s.RegionInfo.RegionName, destination.RegionHandle);
319
320 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
317 return true; 321 return true;
318 } 322 }
319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 323 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 619550c..142567b 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
97 } 97 }
98 } 98 }
99 99
100 /// <summary>
101 /// Used to cache lookups for valid groups.
102 /// </summary>
103 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
104
105 private IGroupsModule m_groupsModule;
106
100 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) 107 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
101 { 108 {
102 m_scene = scene; 109 m_scene = scene;
@@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
120 127
121 // Zero can never be a valid user id 128 // Zero can never be a valid user id
122 m_validUserUuids[UUID.Zero] = false; 129 m_validUserUuids[UUID.Zero] = false;
130
131 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
123 } 132 }
124 133
125 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 134 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
@@ -132,6 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
132 141
133 // Zero can never be a valid user id 142 // Zero can never be a valid user id
134 m_validUserUuids[UUID.Zero] = false; 143 m_validUserUuids[UUID.Zero] = false;
144
145 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
135 } 146 }
136 147
137 /// <summary> 148 /// <summary>
@@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
302 if (!ResolveUserUuid(part.LastOwnerID)) 313 if (!ResolveUserUuid(part.LastOwnerID))
303 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 314 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
304 315
316 if (!ResolveGroupUuid(part.GroupID))
317 part.GroupID = UUID.Zero;
318
305 // And zap any troublesome sit target information 319 // And zap any troublesome sit target information
306// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 320// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
307// part.SitTargetPosition = new Vector3(0, 0, 0); 321// part.SitTargetPosition = new Vector3(0, 0, 0);
@@ -335,13 +349,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
335 { 349 {
336 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 350 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
337 } 351 }
352
338 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 353 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
339 { 354 {
340 if (!ResolveUserUuid(kvp.Value.CreatorID)) 355 if (!ResolveUserUuid(kvp.Value.CreatorID))
341 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 356 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
342 } 357 }
358
343 if (UserManager != null) 359 if (UserManager != null)
344 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 360 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
361
362 if (!ResolveGroupUuid(kvp.Value.GroupID))
363 kvp.Value.GroupID = UUID.Zero;
345 } 364 }
346 part.TaskInventory.LockItemsForRead(false); 365 part.TaskInventory.LockItemsForRead(false);
347 } 366 }
@@ -382,9 +401,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
382 foreach (string serialisedParcel in serialisedParcels) 401 foreach (string serialisedParcel in serialisedParcels)
383 { 402 {
384 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 403 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
404
405 // Validate User and Group UUID's
406
385 if (!ResolveUserUuid(parcel.OwnerID)) 407 if (!ResolveUserUuid(parcel.OwnerID))
386 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 408 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
387 409
410 if (!ResolveGroupUuid(parcel.GroupID))
411 {
412 parcel.GroupID = UUID.Zero;
413 parcel.IsGroupOwned = false;
414 }
415
416 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
417 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
418 {
419 if (ResolveUserUuid(entry.AgentID))
420 accessList.Add(entry);
421 // else, drop this access rule
422 }
423 parcel.ParcelAccessList = accessList;
424
388// m_log.DebugFormat( 425// m_log.DebugFormat(
389// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 426// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
390// parcel.Name, parcel.LocalID, parcel.Area); 427// parcel.Name, parcel.LocalID, parcel.Area);
@@ -419,6 +456,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
419 } 456 }
420 457
421 /// <summary> 458 /// <summary>
459 /// Look up the given group id to check whether it's one that is valid for this grid.
460 /// </summary>
461 /// <param name="uuid"></param>
462 /// <returns></returns>
463 private bool ResolveGroupUuid(UUID uuid)
464 {
465 if (uuid == UUID.Zero)
466 return true; // this means the object has no group
467
468 if (!m_validGroupUuids.ContainsKey(uuid))
469 {
470 bool exists;
471
472 if (m_groupsModule == null)
473 exists = false;
474 else
475 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
476
477 m_validGroupUuids.Add(uuid, exists);
478 }
479
480 return m_validGroupUuids[uuid];
481 }
482
422 /// Load an asset 483 /// Load an asset
423 /// </summary> 484 /// </summary>
424 /// <param name="assetFilename"></param> 485 /// <param name="assetFilename"></param>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 5deaf52..904110e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -51,7 +51,7 @@ using RegionSettings = OpenSim.Framework.RegionSettings;
51namespace OpenSim.Region.CoreModules.World.Archiver.Tests 51namespace OpenSim.Region.CoreModules.World.Archiver.Tests
52{ 52{
53 [TestFixture] 53 [TestFixture]
54 public class ArchiverTests 54 public class ArchiverTests : OpenSimTestCase
55 { 55 {
56 private Guid m_lastRequestId; 56 private Guid m_lastRequestId;
57 private string m_lastErrorMessage; 57 private string m_lastErrorMessage;
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 14c1a39..a2f0950 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -85,13 +85,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
85 dis = 0; 85 dis = 0;
86 } 86 }
87 87
88 float thisSpGain;
89
88 // Scale by distance 90 // Scale by distance
89 if (radius == 0) 91 if (radius == 0)
90 gain = (float)((double)gain * ((100.0 - dis) / 100.0)); 92 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
91 else 93 else
92 gain = (float)((double)gain * ((radius - dis) / radius)); 94 thisSpGain = (float)((double)gain * ((radius - dis) / radius));
93 95
94 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); 96 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags);
95 }); 97 });
96 } 98 }
97 99
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 402b9fb..d99567c 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
414 private void LoadPlugins() 414 private void LoadPlugins()
415 { 415 {
416 m_plugineffects = new Dictionary<string, ITerrainEffect>(); 416 m_plugineffects = new Dictionary<string, ITerrainEffect>();
417 LoadPlugins(Assembly.GetCallingAssembly());
417 string plugineffectsPath = "Terrain"; 418 string plugineffectsPath = "Terrain";
418 419
419 // Load the files in the Terrain/ dir 420 // Load the files in the Terrain/ dir
@@ -427,34 +428,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain
427 try 428 try
428 { 429 {
429 Assembly library = Assembly.LoadFrom(file); 430 Assembly library = Assembly.LoadFrom(file);
430 foreach (Type pluginType in library.GetTypes()) 431 LoadPlugins(library);
431 { 432 }
432 try 433 catch (BadImageFormatException)
433 { 434 {
434 if (pluginType.IsAbstract || pluginType.IsNotPublic) 435 }
435 continue; 436 }
437 }
436 438
437 string typeName = pluginType.Name; 439 private void LoadPlugins(Assembly library)
440 {
441 foreach (Type pluginType in library.GetTypes())
442 {
443 try
444 {
445 if (pluginType.IsAbstract || pluginType.IsNotPublic)
446 continue;
438 447
439 if (pluginType.GetInterface("ITerrainEffect", false) != null) 448 string typeName = pluginType.Name;
440 {
441 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
442 449
443 InstallPlugin(typeName, terEffect); 450 if (pluginType.GetInterface("ITerrainEffect", false) != null)
444 } 451 {
445 else if (pluginType.GetInterface("ITerrainLoader", false) != null) 452 ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
446 { 453
447 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); 454 InstallPlugin(typeName, terEffect);
448 m_loaders[terLoader.FileExtension] = terLoader; 455 }
449 m_log.Info("L ... " + typeName); 456 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
450 } 457 {
451 } 458 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
452 catch (AmbiguousMatchException) 459 m_loaders[terLoader.FileExtension] = terLoader;
453 { 460 m_log.Info("L ... " + typeName);
454 }
455 } 461 }
456 } 462 }
457 catch (BadImageFormatException) 463 catch (AmbiguousMatchException)
458 { 464 {
459 } 465 }
460 } 466 }
@@ -1178,7 +1184,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1178 1184
1179 private void InterfaceRunPluginEffect(Object[] args) 1185 private void InterfaceRunPluginEffect(Object[] args)
1180 { 1186 {
1181 if ((string) args[0] == "list") 1187 string firstArg = (string)args[0];
1188 if (firstArg == "list")
1182 { 1189 {
1183 m_log.Info("List of loaded plugins"); 1190 m_log.Info("List of loaded plugins");
1184 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1191 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@@ -1187,14 +1194,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1187 } 1194 }
1188 return; 1195 return;
1189 } 1196 }
1190 if ((string) args[0] == "reload") 1197 if (firstArg == "reload")
1191 { 1198 {
1192 LoadPlugins(); 1199 LoadPlugins();
1193 return; 1200 return;
1194 } 1201 }
1195 if (m_plugineffects.ContainsKey((string) args[0])) 1202 if (m_plugineffects.ContainsKey(firstArg))
1196 { 1203 {
1197 m_plugineffects[(string) args[0]].RunEffect(m_channel); 1204 m_plugineffects[firstArg].RunEffect(m_channel);
1198 CheckForTerrainUpdates(); 1205 CheckForTerrainUpdates();
1199 } 1206 }
1200 else 1207 else
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 3c48d07..33f6c3f 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -222,6 +222,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); 222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 } 223 }
224 224
225 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
226 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
227 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
228 // this map tile simply takes a lot of memory.
229 GC.Collect();
230 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
231
225 return bitmap; 232 return bitmap;
226 } 233 }
227 234
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 8954513..6df5cc2 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -25,6 +25,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Drawing;
28using System.IO; 30using System.IO;
29using OpenMetaverse; 31using OpenMetaverse;
30 32
@@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
33 public interface IDynamicTextureManager 35 public interface IDynamicTextureManager
34 { 36 {
35 void RegisterRender(string handleType, IDynamicTextureRender render); 37 void RegisterRender(string handleType, IDynamicTextureRender render);
36 void ReturnData(UUID id, byte[] data); 38
39 /// <summary>
40 /// Used by IDynamicTextureRender implementations to return renders
41 /// </summary>
42 /// <param name='id'></param>
43 /// <param name='data'></param>
44 /// <param name='isReuseable'></param>
45 void ReturnData(UUID id, IDynamicTexture texture);
37 46
38 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
39 int updateTimer); 48 int updateTimer);
@@ -113,11 +122,65 @@ namespace OpenSim.Region.Framework.Interfaces
113 string GetName(); 122 string GetName();
114 string GetContentType(); 123 string GetContentType();
115 bool SupportsAsynchronous(); 124 bool SupportsAsynchronous();
116 byte[] ConvertUrl(string url, string extraParams); 125
117 byte[] ConvertStream(Stream data, string extraParams); 126// /// <summary>
127// /// Return true if converting the input body and extra params data will always result in the same byte[] array
128// /// </summary>
129// /// <remarks>
130// /// This method allows the caller to use a previously generated asset if it has one.
131// /// </remarks>
132// /// <returns></returns>
133// /// <param name='bodyData'></param>
134// /// <param name='extraParams'></param>
135// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
136
137 IDynamicTexture ConvertUrl(string url, string extraParams);
138 IDynamicTexture ConvertData(string bodyData, string extraParams);
139
118 bool AsyncConvertUrl(UUID id, string url, string extraParams); 140 bool AsyncConvertUrl(UUID id, string url, string extraParams);
119 bool AsyncConvertData(UUID id, string bodyData, string extraParams); 141 bool AsyncConvertData(UUID id, string bodyData, string extraParams);
142
120 void GetDrawStringSize(string text, string fontName, int fontSize, 143 void GetDrawStringSize(string text, string fontName, int fontSize,
121 out double xSize, out double ySize); 144 out double xSize, out double ySize);
122 } 145 }
146
147 public interface IDynamicTexture
148 {
149 /// <summary>
150 /// Input commands used to generate this data.
151 /// </summary>
152 /// <remarks>
153 /// Null if input commands were not used.
154 /// </remarks>
155 string InputCommands { get; }
156
157 /// <summary>
158 /// Uri used to generate this data.
159 /// </summary>
160 /// <remarks>
161 /// Null if a uri was not used.
162 /// </remarks>
163 Uri InputUri { get; }
164
165 /// <summary>
166 /// Extra input params used to generate this data.
167 /// </summary>
168 string InputParams { get; }
169
170 /// <summary>
171 /// Texture data.
172 /// </summary>
173 byte[] Data { get; }
174
175 /// <summary>
176 /// Size of texture.
177 /// </summary>
178 Size Size { get; }
179
180 /// <summary>
181 /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
182 /// texture).
183 /// </summary>
184 bool IsReuseable { get; }
185 }
123} 186}
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
index ed71a95..dae7c00 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -46,9 +46,38 @@ namespace OpenSim.Region.Framework.Interfaces
46 /// </summary> 46 /// </summary>
47 event ScriptCommand OnScriptCommand; 47 event ScriptCommand OnScriptCommand;
48 48
49 /// <summary>
50 /// Register an instance method as a script call by method name
51 /// </summary>
52 /// <param name="target"></param>
53 /// <param name="method"></param>
49 void RegisterScriptInvocation(object target, string method); 54 void RegisterScriptInvocation(object target, string method);
55
56 /// <summary>
57 /// Register a static or instance method as a script call by method info
58 /// </summary>
59 /// <param name="target">If target is a Type object, will assume method is static.</param>
60 /// <param name="method"></param>
50 void RegisterScriptInvocation(object target, MethodInfo method); 61 void RegisterScriptInvocation(object target, MethodInfo method);
62
63 /// <summary>
64 /// Register one or more instance methods as script calls by method name
65 /// </summary>
66 /// <param name="target"></param>
67 /// <param name="methods"></param>
51 void RegisterScriptInvocation(object target, string[] methods); 68 void RegisterScriptInvocation(object target, string[] methods);
69
70 /// <summary>
71 /// Register one or more static methods as script calls by method name
72 /// </summary>
73 /// <param name="target"></param>
74 /// <param name="methods"></param>
75 void RegisterScriptInvocation(Type target, string[] methods);
76
77 /// <summary>
78 /// Returns an array of all registered script calls
79 /// </summary>
80 /// <returns></returns>
52 Delegate[] GetScriptInvocationList(); 81 Delegate[] GetScriptInvocationList();
53 82
54 Delegate LookupScriptInvocation(string fname); 83 Delegate LookupScriptInvocation(string fname);
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 457444c..79e9f9d 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
40 void ReleaseURL(string url); 40 void ReleaseURL(string url);
41 void HttpResponse(UUID request, int status, string body); 41 void HttpResponse(UUID request, int status, string body);
42 void HttpContentType(UUID request, string type);
43
42 string GetHttpHeader(UUID request, string header); 44 string GetHttpHeader(UUID request, string header);
43 int GetFreeUrls(); 45 int GetFreeUrls();
44 46
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 1309623..863aa49 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 /// </summary> 93 /// </summary>
94 public void StartScripts() 94 public void StartScripts()
95 { 95 {
96 m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); 96// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
97 97
98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); 98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
99 99
@@ -1986,6 +1986,9 @@ namespace OpenSim.Region.Framework.Scenes
1986 // If child prims have invalid perms, fix them 1986 // If child prims have invalid perms, fix them
1987 grp.AdjustChildPrimPermissions(); 1987 grp.AdjustChildPrimPermissions();
1988 1988
1989 // If child prims have invalid perms, fix them
1990 grp.AdjustChildPrimPermissions();
1991
1989 if (remoteClient == null) 1992 if (remoteClient == null)
1990 { 1993 {
1991 // Autoreturn has a null client. Nothing else does. So 1994 // Autoreturn has a null client. Nothing else does. So
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e970543..16c0d25 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -543,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes
543 if (!InventoryService.AddFolder(folder)) 543 if (!InventoryService.AddFolder(folder))
544 { 544 {
545 m_log.WarnFormat( 545 m_log.WarnFormat(
546 "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", 546 "[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
547 remoteClient.Name, remoteClient.AgentId); 547 remoteClient.Name, remoteClient.AgentId);
548 } 548 }
549 } 549 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 0dae946..66cce60 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -103,8 +103,31 @@ namespace OpenSim.Region.Framework.Scenes
103 /// </summary> 103 /// </summary>
104 public bool CollidablePrims { get; private set; } 104 public bool CollidablePrims { get; private set; }
105 105
106 /// <summary>
107 /// Minimum value of the size of a non-physical prim in each axis
108 /// </summary>
109 public float m_minNonphys = 0.01f;
110
111 /// <summary>
112 /// Maximum value of the size of a non-physical prim in each axis
113 /// </summary>
106 public float m_maxNonphys = 256; 114 public float m_maxNonphys = 256;
115
116 /// <summary>
117 /// Minimum value of the size of a physical prim in each axis
118 /// </summary>
119 public float m_minPhys = 0.01f;
120
121 /// <summary>
122 /// Maximum value of the size of a physical prim in each axis
123 /// </summary>
107 public float m_maxPhys = 10; 124 public float m_maxPhys = 10;
125
126 /// <summary>
127 /// Max prims an object will hold
128 /// </summary>
129 public int m_linksetCapacity = 0;
130
108 public bool m_clampPrimSize; 131 public bool m_clampPrimSize;
109 public bool m_trustBinaries; 132 public bool m_trustBinaries;
110 public bool m_allowScriptCrossings; 133 public bool m_allowScriptCrossings;
@@ -746,12 +769,24 @@ namespace OpenSim.Region.Framework.Scenes
746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 769 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 770 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
748 771
772 m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys);
773 if (RegionInfo.NonphysPrimMin > 0)
774 {
775 m_minNonphys = RegionInfo.NonphysPrimMin;
776 }
777
749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 778 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
750 if (RegionInfo.NonphysPrimMax > 0) 779 if (RegionInfo.NonphysPrimMax > 0)
751 { 780 {
752 m_maxNonphys = RegionInfo.NonphysPrimMax; 781 m_maxNonphys = RegionInfo.NonphysPrimMax;
753 } 782 }
754 783
784 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
785 if (RegionInfo.PhysPrimMin > 0)
786 {
787 m_minPhys = RegionInfo.PhysPrimMin;
788 }
789
755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 790 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
756 791
757 if (RegionInfo.PhysPrimMax > 0) 792 if (RegionInfo.PhysPrimMax > 0)
@@ -759,6 +794,12 @@ namespace OpenSim.Region.Framework.Scenes
759 m_maxPhys = RegionInfo.PhysPrimMax; 794 m_maxPhys = RegionInfo.PhysPrimMax;
760 } 795 }
761 796
797 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
798 if (RegionInfo.LinksetCapacity > 0)
799 {
800 m_linksetCapacity = RegionInfo.LinksetCapacity;
801 }
802
762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 803 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 804 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
764 805
@@ -3715,7 +3756,7 @@ namespace OpenSim.Region.Framework.Scenes
3715 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3756 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3716 sp.Name, sp.UUID, RegionInfo.RegionName); 3757 sp.Name, sp.UUID, RegionInfo.RegionName);
3717 3758
3718 sp.ControllingClient.Close(); 3759 sp.ControllingClient.Close(true, true);
3719 sp = null; 3760 sp = null;
3720 } 3761 }
3721 3762
@@ -4318,15 +4359,18 @@ namespace OpenSim.Region.Framework.Scenes
4318 /// Tell a single agent to disconnect from the region. 4359 /// Tell a single agent to disconnect from the region.
4319 /// </summary> 4360 /// </summary>
4320 /// <param name="agentID"></param> 4361 /// <param name="agentID"></param>
4321 /// <param name="childOnly"></param> 4362 /// <param name="force">
4322 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4363 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4364 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4365 /// </param>
4366 public bool IncomingCloseAgent(UUID agentID, bool force)
4323 { 4367 {
4324 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4368 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4325 4369
4326 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4370 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4327 if (presence != null) 4371 if (presence != null)
4328 { 4372 {
4329 presence.ControllingClient.Close(); 4373 presence.ControllingClient.Close(true, force);
4330 return true; 4374 return true;
4331 } 4375 }
4332 4376
@@ -4532,6 +4576,16 @@ namespace OpenSim.Region.Framework.Scenes
4532 return LandChannel.GetLandObject(x, y).LandData; 4576 return LandChannel.GetLandObject(x, y).LandData;
4533 } 4577 }
4534 4578
4579 /// <summary>
4580 /// Get LandData by position.
4581 /// </summary>
4582 /// <param name="pos"></param>
4583 /// <returns></returns>
4584 public LandData GetLandData(Vector3 pos)
4585 {
4586 return GetLandData(pos.X, pos.Y);
4587 }
4588
4535 public LandData GetLandData(uint x, uint y) 4589 public LandData GetLandData(uint x, uint y)
4536 { 4590 {
4537 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4591 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4780,6 +4834,18 @@ namespace OpenSim.Region.Framework.Scenes
4780 } 4834 }
4781 4835
4782 /// <summary> 4836 /// <summary>
4837 /// Attempt to get the SOG via its UUID
4838 /// </summary>
4839 /// <param name="fullID"></param>
4840 /// <param name="sog"></param>
4841 /// <returns></returns>
4842 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4843 {
4844 sog = GetSceneObjectGroup(fullID);
4845 return sog != null;
4846 }
4847
4848 /// <summary>
4783 /// Get a prim by name from the scene (will return the first 4849 /// Get a prim by name from the scene (will return the first
4784 /// found, if there are more than one prim with the same name) 4850 /// found, if there are more than one prim with the same name)
4785 /// </summary> 4851 /// </summary>
@@ -4811,6 +4877,18 @@ namespace OpenSim.Region.Framework.Scenes
4811 } 4877 }
4812 4878
4813 /// <summary> 4879 /// <summary>
4880 /// Attempt to get a prim via its UUID
4881 /// </summary>
4882 /// <param name="fullID"></param>
4883 /// <param name="sop"></param>
4884 /// <returns></returns>
4885 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
4886 {
4887 sop = GetSceneObjectPart(fullID);
4888 return sop != null;
4889 }
4890
4891 /// <summary>
4814 /// Get a scene object group that contains the prim with the given local id 4892 /// Get a scene object group that contains the prim with the given local id
4815 /// </summary> 4893 /// </summary>
4816 /// <param name="localID"></param> 4894 /// <param name="localID"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e29b2c1..c4b7b27 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes
342 public bool AddNewSceneObject( 342 public bool AddNewSceneObject(
343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) 343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
344 { 344 {
345 AddNewSceneObject(sceneObject, true, false); 345 AddNewSceneObject(sceneObject, attachToBackup, false);
346 346
347 if (pos != null) 347 if (pos != null)
348 sceneObject.AbsolutePosition = (Vector3)pos; 348 sceneObject.AbsolutePosition = (Vector3)pos;
@@ -421,12 +421,9 @@ namespace OpenSim.Region.Framework.Scenes
421 { 421 {
422 Vector3 scale = part.Shape.Scale; 422 Vector3 scale = part.Shape.Scale;
423 423
424 if (scale.X > m_parentScene.m_maxNonphys) 424 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X));
425 scale.X = m_parentScene.m_maxNonphys; 425 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y));
426 if (scale.Y > m_parentScene.m_maxNonphys) 426 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z));
427 scale.Y = m_parentScene.m_maxNonphys;
428 if (scale.Z > m_parentScene.m_maxNonphys)
429 scale.Z = m_parentScene.m_maxNonphys;
430 427
431 part.Shape.Scale = scale; 428 part.Shape.Scale = scale;
432 } 429 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 4798481..18e74c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2742,6 +2742,24 @@ namespace OpenSim.Region.Framework.Scenes
2742 if (objectGroup == this) 2742 if (objectGroup == this)
2743 return; 2743 return;
2744 2744
2745 // If the configured linkset capacity is greater than zero,
2746 // and the new linkset would have a prim count higher than this
2747 // value, do not link it.
2748 if (m_scene.m_linksetCapacity > 0 &&
2749 (PrimCount + objectGroup.PrimCount) >
2750 m_scene.m_linksetCapacity)
2751 {
2752 m_log.DebugFormat(
2753 "[SCENE OBJECT GROUP]: Cannot link group with root" +
2754 " part {0}, {1} ({2} prims) to group with root part" +
2755 " {3}, {4} ({5} prims) because the new linkset" +
2756 " would exceed the configured maximum of {6}",
2757 objectGroup.RootPart.Name, objectGroup.RootPart.UUID,
2758 objectGroup.PrimCount, RootPart.Name, RootPart.UUID,
2759 PrimCount, m_scene.m_linksetCapacity);
2760 return;
2761 }
2762
2745 // 'linkPart' == the root of the group being linked into this group 2763 // 'linkPart' == the root of the group being linked into this group
2746 SceneObjectPart linkPart = objectGroup.m_rootPart; 2764 SceneObjectPart linkPart = objectGroup.m_rootPart;
2747 2765
@@ -3464,17 +3482,17 @@ namespace OpenSim.Region.Framework.Scenes
3464 /// <param name="scale"></param> 3482 /// <param name="scale"></param>
3465 public void GroupResize(Vector3 scale) 3483 public void GroupResize(Vector3 scale)
3466 { 3484 {
3467 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3485 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
3468 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3486 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
3469 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3487 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
3470 3488
3471 PhysicsActor pa = m_rootPart.PhysActor; 3489 PhysicsActor pa = m_rootPart.PhysActor;
3472 3490
3473 if (pa != null && pa.IsPhysical) 3491 if (pa != null && pa.IsPhysical)
3474 { 3492 {
3475 scale.X = Math.Min(scale.X, Scene.m_maxPhys); 3493 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3476 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); 3494 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3477 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); 3495 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3478 } 3496 }
3479 3497
3480 float x = (scale.X / RootPart.Scale.X); 3498 float x = (scale.X / RootPart.Scale.X);
@@ -3505,6 +3523,14 @@ namespace OpenSim.Region.Framework.Scenes
3505 y *= a; 3523 y *= a;
3506 z *= a; 3524 z *= a;
3507 } 3525 }
3526 else if (oldSize.X * x < m_scene.m_minPhys)
3527 {
3528 f = m_scene.m_minPhys / oldSize.X;
3529 a = f / x;
3530 x *= a;
3531 y *= a;
3532 z *= a;
3533 }
3508 3534
3509 if (oldSize.Y * y > m_scene.m_maxPhys) 3535 if (oldSize.Y * y > m_scene.m_maxPhys)
3510 { 3536 {
@@ -3514,6 +3540,14 @@ namespace OpenSim.Region.Framework.Scenes
3514 y *= a; 3540 y *= a;
3515 z *= a; 3541 z *= a;
3516 } 3542 }
3543 else if (oldSize.Y * y < m_scene.m_minPhys)
3544 {
3545 f = m_scene.m_minPhys / oldSize.Y;
3546 a = f / y;
3547 x *= a;
3548 y *= a;
3549 z *= a;
3550 }
3517 3551
3518 if (oldSize.Z * z > m_scene.m_maxPhys) 3552 if (oldSize.Z * z > m_scene.m_maxPhys)
3519 { 3553 {
@@ -3523,6 +3557,14 @@ namespace OpenSim.Region.Framework.Scenes
3523 y *= a; 3557 y *= a;
3524 z *= a; 3558 z *= a;
3525 } 3559 }
3560 else if (oldSize.Z * z < m_scene.m_minPhys)
3561 {
3562 f = m_scene.m_minPhys / oldSize.Z;
3563 a = f / z;
3564 x *= a;
3565 y *= a;
3566 z *= a;
3567 }
3526 } 3568 }
3527 else 3569 else
3528 { 3570 {
@@ -3534,6 +3576,14 @@ namespace OpenSim.Region.Framework.Scenes
3534 y *= a; 3576 y *= a;
3535 z *= a; 3577 z *= a;
3536 } 3578 }
3579 else if (oldSize.X * x < m_scene.m_minNonphys)
3580 {
3581 f = m_scene.m_minNonphys / oldSize.X;
3582 a = f / x;
3583 x *= a;
3584 y *= a;
3585 z *= a;
3586 }
3537 3587
3538 if (oldSize.Y * y > m_scene.m_maxNonphys) 3588 if (oldSize.Y * y > m_scene.m_maxNonphys)
3539 { 3589 {
@@ -3543,6 +3593,14 @@ namespace OpenSim.Region.Framework.Scenes
3543 y *= a; 3593 y *= a;
3544 z *= a; 3594 z *= a;
3545 } 3595 }
3596 else if (oldSize.Y * y < m_scene.m_minNonphys)
3597 {
3598 f = m_scene.m_minNonphys / oldSize.Y;
3599 a = f / y;
3600 x *= a;
3601 y *= a;
3602 z *= a;
3603 }
3546 3604
3547 if (oldSize.Z * z > m_scene.m_maxNonphys) 3605 if (oldSize.Z * z > m_scene.m_maxNonphys)
3548 { 3606 {
@@ -3552,6 +3610,14 @@ namespace OpenSim.Region.Framework.Scenes
3552 y *= a; 3610 y *= a;
3553 z *= a; 3611 z *= a;
3554 } 3612 }
3613 else if (oldSize.Z * z < m_scene.m_minNonphys)
3614 {
3615 f = m_scene.m_minNonphys / oldSize.Z;
3616 a = f / z;
3617 x *= a;
3618 y *= a;
3619 z *= a;
3620 }
3555 } 3621 }
3556 } 3622 }
3557 } 3623 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 56d289f..4af508e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes
790 } 790 }
791 catch (Exception e) 791 catch (Exception e)
792 { 792 {
793 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 793 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
794 } 794 }
795 } 795 }
796 } 796 }
@@ -2972,17 +2972,16 @@ namespace OpenSim.Region.Framework.Scenes
2972 /// <param name="scale"></param> 2972 /// <param name="scale"></param>
2973 public void Resize(Vector3 scale) 2973 public void Resize(Vector3 scale)
2974 { 2974 {
2975 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); 2975 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
2976 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); 2976 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
2977 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); 2977 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2978 2978
2979 PhysicsActor pa = PhysActor; 2979 PhysicsActor pa = PhysActor;
2980
2981 if (pa != null && pa.IsPhysical) 2980 if (pa != null && pa.IsPhysical)
2982 { 2981 {
2983 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); 2982 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
2984 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); 2983 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
2985 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); 2984 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z));
2986 } 2985 }
2987 2986
2988// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 2987// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@@ -3567,23 +3566,32 @@ namespace OpenSim.Region.Framework.Scenes
3567 } 3566 }
3568 3567
3569 /// <summary> 3568 /// <summary>
3570 /// Set the color of prim faces 3569 /// Set the color & alpha of prim faces
3571 /// </summary> 3570 /// </summary>
3572 /// <param name="color"></param>
3573 /// <param name="face"></param> 3571 /// <param name="face"></param>
3574 public void SetFaceColor(Vector3 color, int face) 3572 /// <param name="color"></param>
3573 /// <param name="alpha"></param>
3574 public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha)
3575 { 3575 {
3576 Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f);
3577 float clippedAlpha = alpha.HasValue ?
3578 Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0;
3579
3576 // The only way to get a deep copy/ If we don't do this, we can 3580 // The only way to get a deep copy/ If we don't do this, we can
3577 // mever detect color changes further down. 3581 // never detect color changes further down.
3578 Byte[] buf = Shape.Textures.GetBytes(); 3582 Byte[] buf = Shape.Textures.GetBytes();
3579 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3583 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3580 Color4 texcolor; 3584 Color4 texcolor;
3581 if (face >= 0 && face < GetNumberOfSides()) 3585 if (face >= 0 && face < GetNumberOfSides())
3582 { 3586 {
3583 texcolor = tex.CreateFace((uint)face).RGBA; 3587 texcolor = tex.CreateFace((uint)face).RGBA;
3584 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3588 texcolor.R = clippedColor.X;
3585 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3589 texcolor.G = clippedColor.Y;
3586 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3590 texcolor.B = clippedColor.Z;
3591 if (alpha.HasValue)
3592 {
3593 texcolor.A = clippedAlpha;
3594 }
3587 tex.FaceTextures[face].RGBA = texcolor; 3595 tex.FaceTextures[face].RGBA = texcolor;
3588 UpdateTextureEntry(tex.GetBytes()); 3596 UpdateTextureEntry(tex.GetBytes());
3589 return; 3597 return;
@@ -3595,15 +3603,23 @@ namespace OpenSim.Region.Framework.Scenes
3595 if (tex.FaceTextures[i] != null) 3603 if (tex.FaceTextures[i] != null)
3596 { 3604 {
3597 texcolor = tex.FaceTextures[i].RGBA; 3605 texcolor = tex.FaceTextures[i].RGBA;
3598 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3606 texcolor.R = clippedColor.X;
3599 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3607 texcolor.G = clippedColor.Y;
3600 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3608 texcolor.B = clippedColor.Z;
3609 if (alpha.HasValue)
3610 {
3611 texcolor.A = clippedAlpha;
3612 }
3601 tex.FaceTextures[i].RGBA = texcolor; 3613 tex.FaceTextures[i].RGBA = texcolor;
3602 } 3614 }
3603 texcolor = tex.DefaultTexture.RGBA; 3615 texcolor = tex.DefaultTexture.RGBA;
3604 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3616 texcolor.R = clippedColor.X;
3605 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3617 texcolor.G = clippedColor.Y;
3606 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3618 texcolor.B = clippedColor.Z;
3619 if (alpha.HasValue)
3620 {
3621 texcolor.A = clippedAlpha;
3622 }
3607 tex.DefaultTexture.RGBA = texcolor; 3623 tex.DefaultTexture.RGBA = texcolor;
3608 } 3624 }
3609 UpdateTextureEntry(tex.GetBytes()); 3625 UpdateTextureEntry(tex.GetBytes());
@@ -4891,6 +4907,57 @@ namespace OpenSim.Region.Framework.Scenes
4891 ScheduleFullUpdate(); 4907 ScheduleFullUpdate();
4892 } 4908 }
4893 4909
4910 public void UpdateSlice(float begin, float end)
4911 {
4912 if (end < begin)
4913 {
4914 float temp = begin;
4915 begin = end;
4916 end = temp;
4917 }
4918 end = Math.Min(1f, Math.Max(0f, end));
4919 begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f);
4920 if (begin < 0.02f && end < 0.02f)
4921 {
4922 begin = 0f;
4923 end = 0.02f;
4924 }
4925
4926 ushort uBegin = (ushort)(50000.0 * begin);
4927 ushort uEnd = (ushort)(50000.0 * (1f - end));
4928 bool updatePossiblyNeeded = false;
4929 PrimType primType = GetPrimType();
4930 if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING)
4931 {
4932 if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd)
4933 {
4934 m_shape.ProfileBegin = uBegin;
4935 m_shape.ProfileEnd = uEnd;
4936 updatePossiblyNeeded = true;
4937 }
4938 }
4939 else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd)
4940 {
4941 m_shape.PathBegin = uBegin;
4942 m_shape.PathEnd = uEnd;
4943 updatePossiblyNeeded = true;
4944 }
4945
4946 if (updatePossiblyNeeded && ParentGroup != null)
4947 {
4948 ParentGroup.HasGroupChanged = true;
4949 }
4950 if (updatePossiblyNeeded && PhysActor != null)
4951 {
4952 PhysActor.Shape = m_shape;
4953 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
4954 }
4955 if (updatePossiblyNeeded)
4956 {
4957 ScheduleFullUpdate();
4958 }
4959 }
4960
4894 /// <summary> 4961 /// <summary>
4895 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics 4962 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4896 /// engine can use it. 4963 /// engine can use it.
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a8aa551..adb3d38 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -974,7 +974,9 @@ namespace OpenSim.Region.Framework.Scenes
974 { 974 {
975 if (wasChild && HasAttachments()) 975 if (wasChild && HasAttachments())
976 { 976 {
977 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 977 m_log.DebugFormat(
978 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
979
978 // Resume scripts 980 // Resume scripts
979 Util.FireAndForget(delegate(object x) { 981 Util.FireAndForget(delegate(object x) {
980 foreach (SceneObjectGroup sog in m_attachments) 982 foreach (SceneObjectGroup sog in m_attachments)
@@ -1530,17 +1532,22 @@ namespace OpenSim.Region.Framework.Scenes
1530 bool DCFlagKeyPressed = false; 1532 bool DCFlagKeyPressed = false;
1531 Vector3 agent_control_v3 = Vector3.Zero; 1533 Vector3 agent_control_v3 = Vector3.Zero;
1532 1534
1533 bool oldflying = Flying; 1535 bool newFlying = actor.Flying;
1534 1536
1535 if (ForceFly) 1537 if (ForceFly)
1536 actor.Flying = true; 1538 newFlying = true;
1537 else if (FlyDisabled) 1539 else if (FlyDisabled)
1538 actor.Flying = false; 1540 newFlying = false;
1539 else 1541 else
1540 actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1542 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1541 1543
1542 if (actor.Flying != oldflying) 1544 if (actor.Flying != newFlying)
1545 {
1546 // Note: ScenePresence.Flying is actually fetched from the physical actor
1547 // so setting PhysActor.Flying here also sets the ScenePresence's value.
1548 actor.Flying = newFlying;
1543 update_movementflag = true; 1549 update_movementflag = true;
1550 }
1544 1551
1545 if (ParentID == 0) 1552 if (ParentID == 0)
1546 { 1553 {
@@ -3627,13 +3634,16 @@ namespace OpenSim.Region.Framework.Scenes
3627 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) 3634 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
3628 { 3635 {
3629 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); 3636 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3630 3637
3631 lock (m_attachments) 3638 if (attachmentPoint >= 0)
3632 { 3639 {
3633 foreach (SceneObjectGroup so in m_attachments) 3640 lock (m_attachments)
3634 { 3641 {
3635 if (attachmentPoint == so.AttachmentPoint) 3642 foreach (SceneObjectGroup so in m_attachments)
3636 attachments.Add(so); 3643 {
3644 if (attachmentPoint == so.AttachmentPoint)
3645 attachments.Add(so);
3646 }
3637 } 3647 }
3638 } 3648 }
3639 3649
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 5758869..5faf131 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 141 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 143
144 scene.IncomingCloseAgent(sp.UUID); 144 scene.IncomingCloseAgent(sp.UUID, false);
145 145
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 44d2d45..9457ebb 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -50,9 +50,41 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class UserInventoryTests 53 public class UserInventoryTests : OpenSimTestCase
54 { 54 {
55 [Test] 55 [Test]
56 public void TestCreateInventoryFolders()
57 {
58 TestHelpers.InMethod();
59// TestHelpers.EnableLogging();
60
61 // For this test both folders will have the same name which is legal in SL user inventories.
62 string foldersName = "f1";
63
64 Scene scene = new SceneHelpers().SetupScene();
65 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
66
67 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
68
69 List<InventoryFolderBase> oneFolder
70 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
71
72 Assert.That(oneFolder.Count, Is.EqualTo(1));
73 InventoryFolderBase firstRetrievedFolder = oneFolder[0];
74 Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
75
76 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
77
78 List<InventoryFolderBase> twoFolders
79 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
80
81 Assert.That(twoFolders.Count, Is.EqualTo(2));
82 Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
83 Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
84 Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
85 }
86
87 [Test]
56 public void TestGiveInventoryItem() 88 public void TestGiveInventoryItem()
57 { 89 {
58 TestHelpers.InMethod(); 90 TestHelpers.InMethod();
@@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
83 public void TestGiveInventoryFolder() 115 public void TestGiveInventoryFolder()
84 { 116 {
85 TestHelpers.InMethod(); 117 TestHelpers.InMethod();
86// log4net.Config.XmlConfigurator.Configure(); 118// TestHelpers.EnableLogging();
87 119
88 Scene scene = new SceneHelpers().SetupScene(); 120 Scene scene = new SceneHelpers().SetupScene();
89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 121 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 3b83e58..1660c45 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -890,10 +890,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
890 890
891 public void Close() 891 public void Close()
892 { 892 {
893 Close(true); 893 Close(true, false);
894 } 894 }
895 895
896 public void Close(bool sendStop) 896 public void Close(bool sendStop, bool force)
897 { 897 {
898 Disconnect(); 898 Disconnect();
899 } 899 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 7b20446..f292a75 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
447 // settings allow voice, then whether parcel allows 447 // settings allow voice, then whether parcel allows
448 // voice, if all do retrieve or obtain the parcel 448 // voice, if all do retrieve or obtain the parcel
449 // voice channel 449 // voice channel
450 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 450 LandData land = scene.GetLandData(avatar.AbsolutePosition);
451 451
452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index a30a38d..8a8a31c 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
623 // settings allow voice, then whether parcel allows 623 // settings allow voice, then whether parcel allows
624 // voice, if all do retrieve or obtain the parcel 624 // voice, if all do retrieve or obtain the parcel
625 // voice channel 625 // voice channel
626 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 626 LandData land = scene.GetLandData(avatar.AbsolutePosition);
627 627
628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 705a847..23cc633 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -130,13 +130,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
130 m_scriptModule.PostScriptEvent(script, "link_message", args); 130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 } 131 }
132 132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
133 public void RegisterScriptInvocation(object target, string meth) 146 public void RegisterScriptInvocation(object target, string meth)
134 { 147 {
135 MethodInfo mi = target.GetType().GetMethod(meth, 148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
136 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
137 if (mi == null) 149 if (mi == null)
138 { 150 {
139 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); 151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
140 return; 152 return;
141 } 153 }
142 154
@@ -151,38 +163,54 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
151 163
152 public void RegisterScriptInvocation(object target, MethodInfo mi) 164 public void RegisterScriptInvocation(object target, MethodInfo mi)
153 { 165 {
154 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); 166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
155 167
156 Type delegateType; 168 Type delegateType;
157 var typeArgs = mi.GetParameters() 169 List<Type> typeArgs = mi.GetParameters()
158 .Select(p => p.ParameterType) 170 .Select(p => p.ParameterType)
159 .ToList(); 171 .ToList();
160 172
161 if (mi.ReturnType == typeof(void)) 173 if (mi.ReturnType == typeof(void))
162 { 174 {
163 delegateType = Expression.GetActionType(typeArgs.ToArray()); 175 delegateType = Expression.GetActionType(typeArgs.ToArray());
164 } 176 }
165 else 177 else
166 { 178 {
167 typeArgs.Add(mi.ReturnType); 179 typeArgs.Add(mi.ReturnType);
168 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 180 delegateType = Expression.GetFuncType(typeArgs.ToArray());
169 } 181 }
170 182
171 Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); 183 Delegate fcall;
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
172 188
173 lock (m_scriptInvocation) 189 lock (m_scriptInvocation)
174 { 190 {
175 ParameterInfo[] parameters = fcall.Method.GetParameters (); 191 ParameterInfo[] parameters = fcall.Method.GetParameters();
176 if (parameters.Length < 2) // Must have two UUID params 192 if (parameters.Length < 2) // Must have two UUID params
177 return; 193 return;
178 194
179 // Hide the first two parameters 195 // Hide the first two parameters
180 Type[] parmTypes = new Type[parameters.Length - 2]; 196 Type[] parmTypes = new Type[parameters.Length - 2];
181 for (int i = 2 ; i < parameters.Length ; i++) 197 for (int i = 2; i < parameters.Length; i++)
182 parmTypes[i - 2] = parameters[i].ParameterType; 198 parmTypes[i - 2] = parameters[i].ParameterType;
183 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); 199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
184 } 200 }
185 } 201 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
186 214
187 public Delegate[] GetScriptInvocationList() 215 public Delegate[] GetScriptInvocationList()
188 { 216 {
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index d00a6c0..625342e 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -905,11 +905,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
905 905
906 public void Close() 906 public void Close()
907 { 907 {
908 Close(true); 908 Close(true, false);
909 } 909 }
910 910
911 public void Close(bool sendStop) 911 public void Close(bool sendStop, bool force)
912 { 912 {
913 // Remove ourselves from the scene
914 m_scene.RemoveClient(AgentId, false);
913 } 915 }
914 916
915 public void Start() 917 public void Start()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e2f7af9..fa22c78 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -34,13 +34,12 @@ using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSCharacter : PhysicsActor 37public class BSCharacter : BSPhysObject
38{ 38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene; 42 public BSScene Scene { get; private set; }
43 public BSScene Scene { get { return _scene; } }
44 private String _avName; 43 private String _avName;
45 // private bool _stopped; 44 // private bool _stopped;
46 private Vector3 _size; 45 private Vector3 _size;
@@ -74,11 +73,9 @@ public class BSCharacter : PhysicsActor
74 private bool _kinematic; 73 private bool _kinematic;
75 private float _buoyancy; 74 private float _buoyancy;
76 75
77 private BulletBody m_body; 76 public override BulletBody BSBody { get; set; }
78 public BulletBody Body { 77 public override BulletShape BSShape { get; set; }
79 get { return m_body; } 78 public override BSLinkset Linkset { get; set; }
80 set { m_body = value; }
81 }
82 79
83 private int _subscribedEventsMs = 0; 80 private int _subscribedEventsMs = 0;
84 private int _nextCollisionOkTime = 0; 81 private int _nextCollisionOkTime = 0;
@@ -95,7 +92,8 @@ public class BSCharacter : PhysicsActor
95 { 92 {
96 _localID = localID; 93 _localID = localID;
97 _avName = avName; 94 _avName = avName;
98 _scene = parent_scene; 95 Scene = parent_scene;
96 _physicsActorType = (int)ActorTypes.Agent;
99 _position = pos; 97 _position = pos;
100 _size = size; 98 _size = size;
101 _flying = isFlying; 99 _flying = isFlying;
@@ -104,10 +102,12 @@ public class BSCharacter : PhysicsActor
104 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 102 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
105 // The dimensions of the avatar capsule are kept in the scale. 103 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine. 104 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); 105 _scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z);
108 _density = _scene.Params.avatarDensity; 106 _density = Scene.Params.avatarDensity;
109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 107 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
110 108
109 Linkset = new BSLinkset(Scene, this);
110
111 ShapeData shapeData = new ShapeData(); 111 ShapeData shapeData = new ShapeData();
112 shapeData.ID = _localID; 112 shapeData.ID = _localID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; 113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
@@ -118,29 +118,33 @@ public class BSCharacter : PhysicsActor
118 shapeData.Mass = _mass; 118 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy; 119 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse; 120 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = _scene.Params.avatarFriction; 121 shapeData.Friction = Scene.Params.avatarFriction;
122 shapeData.Restitution = _scene.Params.avatarRestitution; 122 shapeData.Restitution = Scene.Params.avatarRestitution;
123 123
124 // do actual create at taint time 124 // do actual create at taint time
125 _scene.TaintedObject("BSCharacter.create", delegate() 125 Scene.TaintedObject("BSCharacter.create", delegate()
126 { 126 {
127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 127 DetailLog("{0},BSCharacter.create", _localID);
128 BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
129
130 // Set the buoyancy for flying. This will be refactored when all the settings happen in C#
131 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
128 132
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 133 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
130 // avatars get all collisions no matter what 134 // avatars get all collisions no matter what (makes walking on ground and such work)
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 135 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
132 }); 136 });
133 137
134 return; 138 return;
135 } 139 }
136 140
137 // called when this character is being destroyed and the resources should be released 141 // called when this character is being destroyed and the resources should be released
138 public void Destroy() 142 public override void Destroy()
139 { 143 {
140 // DetailLog("{0},BSCharacter.Destroy", LocalID); 144 DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate() 145 Scene.TaintedObject("BSCharacter.destroy", delegate()
142 { 146 {
143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 147 BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
144 }); 148 });
145 } 149 }
146 150
@@ -169,9 +173,9 @@ public class BSCharacter : PhysicsActor
169 173
170 ComputeAvatarVolumeAndMass(); 174 ComputeAvatarVolumeAndMass();
171 175
172 _scene.TaintedObject("BSCharacter.setSize", delegate() 176 Scene.TaintedObject("BSCharacter.setSize", delegate()
173 { 177 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); 178 BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true);
175 }); 179 });
176 180
177 } 181 }
@@ -200,17 +204,17 @@ public class BSCharacter : PhysicsActor
200 204
201 public override Vector3 Position { 205 public override Vector3 Position {
202 get { 206 get {
203 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 207 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
204 return _position; 208 return _position;
205 } 209 }
206 set { 210 set {
207 _position = value; 211 _position = value;
208 PositionSanityCheck(); 212 PositionSanityCheck();
209 213
210 _scene.TaintedObject("BSCharacter.setPosition", delegate() 214 Scene.TaintedObject("BSCharacter.setPosition", delegate()
211 { 215 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 216 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 217 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
214 }); 218 });
215 } 219 }
216 } 220 }
@@ -223,16 +227,35 @@ public class BSCharacter : PhysicsActor
223 bool ret = false; 227 bool ret = false;
224 228
225 // If below the ground, move the avatar up 229 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); 230 float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight) 231 if (Position.Z < terrainHeight)
228 { 232 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); 233 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
230 _position.Z = terrainHeight + 2.0f; 234 _position.Z = terrainHeight + 2.0f;
231 ret = true; 235 ret = true;
232 } 236 }
233 237
234 // TODO: check for out of bounds 238 // TODO: check for out of bounds
239 return ret;
240 }
235 241
242 // A version of the sanity check that also makes sure a new position value is
243 // pushed back to the physics engine. This routine would be used by anyone
244 // who is not already pushing the value.
245 private bool PositionSanityCheck2()
246 {
247 bool ret = false;
248 if (PositionSanityCheck())
249 {
250 // The new position value must be pushed into the physics engine but we can't
251 // just assign to "Position" because of potential call loops.
252 Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
253 {
254 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
255 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
256 });
257 ret = true;
258 }
236 return ret; 259 return ret;
237 } 260 }
238 261
@@ -241,6 +264,10 @@ public class BSCharacter : PhysicsActor
241 return _mass; 264 return _mass;
242 } 265 }
243 } 266 }
267
268 // used when we only want this prim's mass and not the linkset thing
269 public override float MassRaw { get {return _mass; } }
270
244 public override Vector3 Force { 271 public override Vector3 Force {
245 get { return _force; } 272 get { return _force; }
246 set { 273 set {
@@ -273,10 +300,10 @@ public class BSCharacter : PhysicsActor
273 set { 300 set {
274 _velocity = value; 301 _velocity = value;
275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 302 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
276 _scene.TaintedObject("BSCharacter.setVelocity", delegate() 303 Scene.TaintedObject("BSCharacter.setVelocity", delegate()
277 { 304 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 305 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 306 BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
280 }); 307 });
281 } 308 }
282 } 309 }
@@ -299,10 +326,10 @@ public class BSCharacter : PhysicsActor
299 set { 326 set {
300 _orientation = value; 327 _orientation = value;
301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 328 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
302 _scene.TaintedObject("BSCharacter.setOrientation", delegate() 329 Scene.TaintedObject("BSCharacter.setOrientation", delegate()
303 { 330 {
304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 331 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 332 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
306 }); 333 });
307 } 334 }
308 } 335 }
@@ -319,14 +346,13 @@ public class BSCharacter : PhysicsActor
319 public override bool Flying { 346 public override bool Flying {
320 get { return _flying; } 347 get { return _flying; }
321 set { 348 set {
322 if (_flying != value) 349 _flying = value;
323 { 350 // simulate flying by changing the effect of gravity
324 _flying = value; 351 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
328 } 352 }
329 } 353 }
354 // Flying is implimented by changing the avatar's buoyancy.
355 // Would this be done better with a vehicle type?
330 private float ComputeBuoyancyFromFlying(bool ifFlying) { 356 private float ComputeBuoyancyFromFlying(bool ifFlying) {
331 return ifFlying ? 1f : 0f; 357 return ifFlying ? 1f : 0f;
332 } 358 }
@@ -340,11 +366,11 @@ public class BSCharacter : PhysicsActor
340 set { _throttleUpdates = value; } 366 set { _throttleUpdates = value; }
341 } 367 }
342 public override bool IsColliding { 368 public override bool IsColliding {
343 get { return (_collidingStep == _scene.SimulationStep); } 369 get { return (_collidingStep == Scene.SimulationStep); }
344 set { _isColliding = value; } 370 set { _isColliding = value; }
345 } 371 }
346 public override bool CollidingGround { 372 public override bool CollidingGround {
347 get { return (_collidingGroundStep == _scene.SimulationStep); } 373 get { return (_collidingGroundStep == Scene.SimulationStep); }
348 set { _collidingGround = value; } 374 set { _collidingGround = value; }
349 } 375 }
350 public override bool CollidingObj { 376 public override bool CollidingObj {
@@ -366,10 +392,10 @@ public class BSCharacter : PhysicsActor
366 public override float Buoyancy { 392 public override float Buoyancy {
367 get { return _buoyancy; } 393 get { return _buoyancy; }
368 set { _buoyancy = value; 394 set { _buoyancy = value;
369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 395 Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
370 { 396 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 397 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 398 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
373 }); 399 });
374 } 400 }
375 } 401 }
@@ -413,10 +439,10 @@ public class BSCharacter : PhysicsActor
413 _force.Y += force.Y; 439 _force.Y += force.Y;
414 _force.Z += force.Z; 440 _force.Z += force.Z;
415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 441 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
416 _scene.TaintedObject("BSCharacter.AddForce", delegate() 442 Scene.TaintedObject("BSCharacter.AddForce", delegate()
417 { 443 {
418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 444 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force); 445 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
420 }); 446 });
421 } 447 }
422 else 448 else
@@ -441,10 +467,16 @@ public class BSCharacter : PhysicsActor
441 467
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() 468 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
443 { 469 {
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 470 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 }); 471 });
446 } 472 }
447 } 473 }
474
475 public override void ZeroMotion()
476 {
477 return;
478 }
479
448 // Stop collision events 480 // Stop collision events
449 public override void UnSubscribeEvents() { 481 public override void UnSubscribeEvents() {
450 _subscribedEventsMs = 0; 482 _subscribedEventsMs = 0;
@@ -478,7 +510,7 @@ public class BSCharacter : PhysicsActor
478 510
479 // The physics engine says that properties have updated. Update same and inform 511 // The physics engine says that properties have updated. Update same and inform
480 // the world that things have changed. 512 // the world that things have changed.
481 public void UpdateProperties(EntityProperties entprop) 513 public override void UpdateProperties(EntityProperties entprop)
482 { 514 {
483 _position = entprop.Position; 515 _position = entprop.Position;
484 _orientation = entprop.Rotation; 516 _orientation = entprop.Rotation;
@@ -488,32 +520,33 @@ public class BSCharacter : PhysicsActor
488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 520 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
489 // base.RequestPhysicsterseUpdate(); 521 // base.RequestPhysicsterseUpdate();
490 522
491 /* 523 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 524 PositionSanityCheck2();
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 525
494 entprop.Acceleration, entprop.RotationalVelocity); 526 float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
495 */ 527 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
528 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
496 } 529 }
497 530
498 // Called by the scene when a collision with this object is reported 531 // Called by the scene when a collision with this object is reported
499 // The collision, if it should be reported to the character, is placed in a collection 532 // The collision, if it should be reported to the character, is placed in a collection
500 // that will later be sent to the simulator when SendCollisions() is called. 533 // that will later be sent to the simulator when SendCollisions() is called.
501 CollisionEventUpdate collisionCollection = null; 534 CollisionEventUpdate collisionCollection = null;
502 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 535 public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
503 { 536 {
504 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 537 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
505 538
506 // The following makes IsColliding() and IsCollidingGround() work 539 // The following makes IsColliding() and IsCollidingGround() work
507 _collidingStep = _scene.SimulationStep; 540 _collidingStep = Scene.SimulationStep;
508 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 541 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
509 { 542 {
510 _collidingGroundStep = _scene.SimulationStep; 543 _collidingGroundStep = Scene.SimulationStep;
511 } 544 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); 545 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
513 546
514 // throttle collisions to the rate specified in the subscription 547 // throttle collisions to the rate specified in the subscription
515 if (_subscribedEventsMs != 0) { 548 if (_subscribedEventsMs != 0) {
516 int nowTime = _scene.SimulationNowTime; 549 int nowTime = Scene.SimulationNowTime;
517 if (nowTime >= _nextCollisionOkTime) { 550 if (nowTime >= _nextCollisionOkTime) {
518 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 551 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
519 552
@@ -524,7 +557,7 @@ public class BSCharacter : PhysicsActor
524 } 557 }
525 } 558 }
526 559
527 public void SendCollisions() 560 public override void SendCollisions()
528 { 561 {
529 /* 562 /*
530 if (collisionCollection != null && collisionCollection.Count > 0) 563 if (collisionCollection != null && collisionCollection.Count > 0)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 25084d8..2e15ced 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -48,11 +48,10 @@ public abstract class BSConstraint : IDisposable
48 { 48 {
49 if (m_enabled) 49 if (m_enabled)
50 { 50 {
51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); 51 m_enabled = false;
52 bool success = 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); 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; 54 m_constraint.Ptr = System.IntPtr.Zero;
55 m_enabled = false;
56 } 55 }
57 } 56 }
58 57
@@ -99,6 +98,10 @@ public abstract class BSConstraint : IDisposable
99 { 98 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", 99 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID); 100 // BSScene.DetailLogZero, Body1.ID, Body2.ID);
101
102 // Setting an object's mass to zero (making it static like when it's selected)
103 // automatically disables the constraints.
104 // If enabled, be sure to set the constraint itself to enabled.
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); 105 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
103 } 106 }
104 else 107 else
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5a9f135..8169e99 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // every 100th frame 58 // every 100th frame
59 59
60 private BSScene m_physicsScene;
60 private BSPrim m_prim; // the prim this dynamic controller belongs to 61 private BSPrim m_prim; // the prim this dynamic controller belongs to
61 62
62 // Vehicle properties 63 // Vehicle properties
@@ -74,7 +75,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
74 // HOVER_UP_ONLY 75 // HOVER_UP_ONLY
75 // LIMIT_MOTOR_UP 76 // LIMIT_MOTOR_UP
76 // LIMIT_ROLL_ONLY 77 // LIMIT_ROLL_ONLY
77 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
78 private Vector3 m_BlockingEndPoint = Vector3.Zero; 78 private Vector3 m_BlockingEndPoint = Vector3.Zero;
79 private Quaternion m_RollreferenceFrame = Quaternion.Identity; 79 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
80 // Linear properties 80 // Linear properties
@@ -124,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 private float m_verticalAttractionEfficiency = 1.0f; // damped 124 private float m_verticalAttractionEfficiency = 1.0f; // damped
125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
126 126
127 public BSDynamics(BSPrim myPrim) 127 public BSDynamics(BSScene myScene, BSPrim myPrim)
128 { 128 {
129 m_physicsScene = myScene;
129 m_prim = myPrim; 130 m_prim = myPrim;
130 m_type = Vehicle.TYPE_NONE; 131 m_type = Vehicle.TYPE_NONE;
131 } 132 }
132 133
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
134 { 135 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 136 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
136 switch (pParam) 137 switch (pParam)
137 { 138 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 139 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@@ -231,7 +232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
231 232
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 233 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
233 { 234 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 235 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
235 switch (pParam) 236 switch (pParam)
236 { 237 {
237 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 238 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -266,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
266 267
267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 268 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
268 { 269 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 270 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
270 switch (pParam) 271 switch (pParam)
271 { 272 {
272 case Vehicle.REFERENCE_FRAME: 273 case Vehicle.REFERENCE_FRAME:
@@ -280,164 +281,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
280 281
281 internal void ProcessVehicleFlags(int pParam, bool remove) 282 internal void ProcessVehicleFlags(int pParam, bool remove)
282 { 283 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); 284 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
285 VehicleFlag parm = (VehicleFlag)pParam;
284 if (remove) 286 if (remove)
285 { 287 {
286 if (pParam == -1) 288 if (pParam == -1)
287 { 289 {
288 m_flags = (VehicleFlag)0; 290 m_flags = (VehicleFlag)0;
289 m_Hoverflags = (VehicleFlag)0;
290 return;
291 } 291 }
292 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) 292 else
293 {
294 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
295 m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
296 }
297 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
298 {
299 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
300 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
301 }
302 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
303 {
304 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
305 m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
306 }
307 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
308 {
309 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
310 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
311 }
312 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
313 {
314 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
315 m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
316 }
317 if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
318 {
319 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
320 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
321 }
322 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
323 {
324 if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
325 m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
326 }
327 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
328 {
329 if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
330 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
331 }
332 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
333 {
334 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
335 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
336 }
337 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
338 {
339 if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
340 m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
341 }
342 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
343 {
344 if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
345 m_flags &= ~(VehicleFlag.NO_X);
346 }
347 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
348 {
349 if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
350 m_flags &= ~(VehicleFlag.NO_Y);
351 }
352 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
353 {
354 if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
355 m_flags &= ~(VehicleFlag.NO_Z);
356 }
357 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
358 {
359 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
360 m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
361 }
362 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
363 {
364 if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
365 m_flags &= ~(VehicleFlag.NO_DEFLECTION);
366 }
367 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
368 { 293 {
369 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) 294 m_flags &= ~parm;
370 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
371 } 295 }
372 } 296 }
373 else 297 else {
374 { 298 m_flags |= parm;
375 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
376 {
377 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
378 }
379 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
380 {
381 m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
382 }
383 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
384 {
385 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
386 }
387 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
388 {
389 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
390 }
391 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
392 {
393 m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
394 }
395 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
396 {
397 m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
398 }
399 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
400 {
401 m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
402 }
403 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
404 {
405 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
406 }
407 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
408 {
409 m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
410 }
411 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
412 {
413 m_flags |= (VehicleFlag.NO_X);
414 }
415 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
416 {
417 m_flags |= (VehicleFlag.NO_Y);
418 }
419 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
420 {
421 m_flags |= (VehicleFlag.NO_Z);
422 }
423 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
424 {
425 m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
426 }
427 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
428 {
429 m_flags |= (VehicleFlag.NO_DEFLECTION);
430 }
431 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
432 {
433 m_flags |= (VehicleFlag.LOCK_ROTATION);
434 }
435 } 299 }
436 }//end ProcessVehicleFlags 300 }//end ProcessVehicleFlags
437 301
438 internal void ProcessTypeChange(Vehicle pType) 302 internal void ProcessTypeChange(Vehicle pType, float stepSize)
439 { 303 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); 304 VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
441 // Set Defaults For Type 305 // Set Defaults For Type
442 m_type = pType; 306 m_type = pType;
443 switch (pType) 307 switch (pType)
@@ -478,10 +342,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
478 // m_bankingMix = 1; 342 // m_bankingMix = 1;
479 // m_bankingTimescale = 10; 343 // m_bankingTimescale = 10;
480 // m_referenceFrame = Quaternion.Identity; 344 // m_referenceFrame = Quaternion.Identity;
481 m_Hoverflags &= 345 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
346 m_flags &=
482 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 347 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
483 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 348 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
484 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
485 break; 349 break;
486 case Vehicle.TYPE_CAR: 350 case Vehicle.TYPE_CAR:
487 m_linearFrictionTimescale = new Vector3(100, 2, 1000); 351 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
@@ -506,10 +370,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
506 // m_bankingMix = 1; 370 // m_bankingMix = 1;
507 // m_bankingTimescale = 1; 371 // m_bankingTimescale = 1;
508 // m_referenceFrame = Quaternion.Identity; 372 // m_referenceFrame = Quaternion.Identity;
509 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
510 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | 373 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
511 VehicleFlag.LIMIT_MOTOR_UP); 374 VehicleFlag.LIMIT_MOTOR_UP);
512 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); 375 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
376 m_flags |= (VehicleFlag.HOVER_UP_ONLY);
513 break; 377 break;
514 case Vehicle.TYPE_BOAT: 378 case Vehicle.TYPE_BOAT:
515 m_linearFrictionTimescale = new Vector3(10, 3, 2); 379 m_linearFrictionTimescale = new Vector3(10, 3, 2);
@@ -534,12 +398,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
534 // m_bankingMix = 0.8f; 398 // m_bankingMix = 0.8f;
535 // m_bankingTimescale = 1; 399 // m_bankingTimescale = 1;
536 // m_referenceFrame = Quaternion.Identity; 400 // m_referenceFrame = Quaternion.Identity;
537 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | 401 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
538 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 402 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
539 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); 403 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
540 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | 404 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
541 VehicleFlag.LIMIT_MOTOR_UP); 405 VehicleFlag.LIMIT_MOTOR_UP);
542 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); 406 m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
543 break; 407 break;
544 case Vehicle.TYPE_AIRPLANE: 408 case Vehicle.TYPE_AIRPLANE:
545 m_linearFrictionTimescale = new Vector3(200, 10, 5); 409 m_linearFrictionTimescale = new Vector3(200, 10, 5);
@@ -564,7 +428,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
564 // m_bankingMix = 0.7f; 428 // m_bankingMix = 0.7f;
565 // m_bankingTimescale = 2; 429 // m_bankingTimescale = 2;
566 // m_referenceFrame = Quaternion.Identity; 430 // m_referenceFrame = Quaternion.Identity;
567 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 431 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
568 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 432 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
569 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 433 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
570 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 434 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
@@ -592,15 +456,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
592 // m_bankingMix = 0.7f; 456 // m_bankingMix = 0.7f;
593 // m_bankingTimescale = 5; 457 // m_bankingTimescale = 5;
594 // m_referenceFrame = Quaternion.Identity; 458 // m_referenceFrame = Quaternion.Identity;
595 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 459 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
596 VehicleFlag.HOVER_UP_ONLY); 460 VehicleFlag.HOVER_UP_ONLY);
597 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 461 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 462 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 463 m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
600 break; 464 break;
601 } 465 }
602 }//end SetDefaultsForType 466 }//end SetDefaultsForType
603 467
468 // One step of the vehicle properties for the next 'pTimestep' seconds.
604 internal void Step(float pTimestep) 469 internal void Step(float pTimestep)
605 { 470 {
606 if (m_type == Vehicle.TYPE_NONE) return; 471 if (m_type == Vehicle.TYPE_NONE) return;
@@ -613,7 +478,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
613 MoveAngular(pTimestep); 478 MoveAngular(pTimestep);
614 LimitRotation(pTimestep); 479 LimitRotation(pTimestep);
615 480
616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 481 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 482 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
618 }// end Step 483 }// end Step
619 484
@@ -657,7 +522,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
657 522
658 */ 523 */
659 524
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", 525 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); 526 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
662 } 527 }
663 else 528 else
@@ -669,7 +534,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
669 m_lastLinearVelocityVector = Vector3.Zero; 534 m_lastLinearVelocityVector = Vector3.Zero;
670 } 535 }
671 536
672 // convert requested object velocity to world-referenced vector 537 // convert requested object velocity to object relative vector
673 Quaternion rotq = m_prim.Orientation; 538 Quaternion rotq = m_prim.Orientation;
674 m_dir = m_lastLinearVelocityVector * rotq; 539 m_dir = m_lastLinearVelocityVector * rotq;
675 540
@@ -722,42 +587,42 @@ namespace OpenSim.Region.Physics.BulletSPlugin
722 if (changed) 587 if (changed)
723 { 588 {
724 m_prim.Position = pos; 589 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 590 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos); 591 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
727 } 592 }
728 } 593 }
729 594
730 // If below the terrain, move us above the ground a little. 595 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) 596 if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
732 { 597 {
733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; 598 pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
734 m_prim.Position = pos; 599 m_prim.Position = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 600 VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
736 } 601 }
737 602
738 // Check if hovering 603 // Check if hovering
739 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 604 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
740 { 605 {
741 // We should hover, get the target height 606 // We should hover, get the target height
742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 607 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
743 { 608 {
744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 609 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
745 } 610 }
746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 611 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
747 { 612 {
748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 613 m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
749 } 614 }
750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 615 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
751 { 616 {
752 m_VhoverTargetHeight = m_VhoverHeight; 617 m_VhoverTargetHeight = m_VhoverHeight;
753 } 618 }
754 619
755 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) 620 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
756 { 621 {
757 // If body is aready heigher, use its height as target height 622 // If body is aready heigher, use its height as target height
758 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 623 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
759 } 624 }
760 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 625 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
761 { 626 {
762 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) 627 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
763 { 628 {
@@ -779,7 +644,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
779 } 644 }
780 } 645 }
781 646
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 647 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
783 648
784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 649// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
785// m_VhoverTimescale = 0f; // time to acheive height 650// m_VhoverTimescale = 0f; // time to acheive height
@@ -809,13 +674,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
809 { 674 {
810 grav.Z = (float)(grav.Z * 1.125); 675 grav.Z = (float)(grav.Z * 1.125);
811 } 676 }
812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); 677 float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
813 float postemp = (pos.Z - terraintemp); 678 float postemp = (pos.Z - terraintemp);
814 if (postemp > 2.5f) 679 if (postemp > 2.5f)
815 { 680 {
816 grav.Z = (float)(grav.Z * 1.037125); 681 grav.Z = (float)(grav.Z * 1.037125);
817 } 682 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); 683 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
819 //End Experimental Values 684 //End Experimental Values
820 } 685 }
821 if ((m_flags & (VehicleFlag.NO_X)) != 0) 686 if ((m_flags & (VehicleFlag.NO_X)) != 0)
@@ -844,7 +709,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 709 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 710 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846 711
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 712 VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 713 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
849 714
850 } // end MoveLinear() 715 } // end MoveLinear()
@@ -870,13 +735,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
870 // There are m_angularMotorApply steps. 735 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity; 736 Vector3 origAngularVelocity = m_angularMotorVelocity;
872 // ramp up to new value 737 // ramp up to new value
873 // current velocity += error / (time to get there / step interval) 738 // current velocity += error / (time to get there / step interval)
874 // requested speed - last motor speed 739 // requested speed - last motor speed
875 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 740 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 741 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 742 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
878 743
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", 744 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); 745 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881 746
882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 747 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
@@ -887,6 +752,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
887 // No motor recently applied, keep the body velocity 752 // No motor recently applied, keep the body velocity
888 // and decay the velocity 753 // and decay the velocity
889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 754 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
755 if (m_angularMotorVelocity.LengthSquared() < 0.00001)
756 m_angularMotorVelocity = Vector3.Zero;
890 } // end motor section 757 } // end motor section
891 758
892 // Vertical attractor section 759 // Vertical attractor section
@@ -924,7 +791,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
924 vertattr.X += bounce * angularVelocity.X; 791 vertattr.X += bounce * angularVelocity.X;
925 vertattr.Y += bounce * angularVelocity.Y; 792 vertattr.Y += bounce * angularVelocity.Y;
926 793
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", 794 VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr); 795 m_prim.LocalID, verterr, bounce, vertattr);
929 796
930 } // else vertical attractor is off 797 } // else vertical attractor is off
@@ -942,13 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
942 { 809 {
943 m_lastAngularVelocity.X = 0; 810 m_lastAngularVelocity.X = 0;
944 m_lastAngularVelocity.Y = 0; 811 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 812 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
946 } 813 }
947 814
948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 815 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
949 { 816 {
950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 817 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 818 VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
952 } 819 }
953 820
954 // apply friction 821 // apply friction
@@ -958,7 +825,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
958 // Apply to the body 825 // Apply to the body
959 m_prim.RotationalVelocity = m_lastAngularVelocity; 826 m_prim.RotationalVelocity = m_lastAngularVelocity;
960 827
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); 828 VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
962 } //end MoveAngular 829 } //end MoveAngular
963 830
964 internal void LimitRotation(float timestep) 831 internal void LimitRotation(float timestep)
@@ -1005,11 +872,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1005 if (changed) 872 if (changed)
1006 m_prim.Orientation = m_rot; 873 m_prim.Orientation = m_rot;
1007 874
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); 875 VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 } 876 }
1010 877
1011 // Invoke the detailed logger and output something if it's enabled. 878 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args) 879 private void VDetailLog(string msg, params Object[] args)
1013 { 880 {
1014 if (m_prim.Scene.VehicleLoggingEnabled) 881 if (m_prim.Scene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args); 882 m_prim.Scene.PhysicsLogging.Write(msg, args);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 087b9bb..5f6601d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -36,14 +36,17 @@ public class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 private BSPhysObject m_linksetRoot;
40 public BSPrim LinksetRoot { get { return m_linksetRoot; } } 40 public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
41 41
42 private BSScene m_physicsScene; 42 private BSScene m_physicsScene;
43 public BSScene PhysicsScene { get { return m_physicsScene; } } 43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 44
45 static int m_nextLinksetID = 1;
46 public int LinksetID { get; private set; }
47
45 // The children under the root in this linkset 48 // The children under the root in this linkset
46 private List<BSPrim> m_children; 49 private List<BSPhysObject> m_children;
47 50
48 // We lock the diddling of linkset classes to prevent any badness. 51 // We lock the diddling of linkset classes to prevent any badness.
49 // This locks the modification of the instances of this class. Changes 52 // This locks the modification of the instances of this class. Changes
@@ -71,19 +74,23 @@ public class BSLinkset
71 get { return ComputeLinksetGeometricCenter(); } 74 get { return ComputeLinksetGeometricCenter(); }
72 } 75 }
73 76
74 public BSLinkset(BSScene scene, BSPrim parent) 77 public BSLinkset(BSScene scene, BSPhysObject parent)
75 { 78 {
76 // A simple linkset of one (no children) 79 // A simple linkset of one (no children)
80 LinksetID = m_nextLinksetID++;
81 // We create LOTS of linksets.
82 if (m_nextLinksetID < 0)
83 m_nextLinksetID = 1;
77 m_physicsScene = scene; 84 m_physicsScene = scene;
78 m_linksetRoot = parent; 85 m_linksetRoot = parent;
79 m_children = new List<BSPrim>(); 86 m_children = new List<BSPhysObject>();
80 m_mass = parent.MassRaw; 87 m_mass = parent.MassRaw;
81 } 88 }
82 89
83 // Link to a linkset where the child knows the parent. 90 // Link to a linkset where the child knows the parent.
84 // Parent changing should not happen so do some sanity checking. 91 // Parent changing should not happen so do some sanity checking.
85 // We return the parent's linkset so the child can track its membership. 92 // We return the parent's linkset so the child can track its membership.
86 public BSLinkset AddMeToLinkset(BSPrim child) 93 public BSLinkset AddMeToLinkset(BSPhysObject child)
87 { 94 {
88 lock (m_linksetActivityLock) 95 lock (m_linksetActivityLock)
89 { 96 {
@@ -95,7 +102,7 @@ public class BSLinkset
95 // Remove a child from a linkset. 102 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the 103 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child). 104 // orphened child).
98 public BSLinkset RemoveMeFromLinkset(BSPrim child) 105 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
99 { 106 {
100 lock (m_linksetActivityLock) 107 lock (m_linksetActivityLock)
101 { 108 {
@@ -122,7 +129,7 @@ public class BSLinkset
122 } 129 }
123 130
124 // Return 'true' if the passed object is the root object of this linkset 131 // Return 'true' if the passed object is the root object of this linkset
125 public bool IsRoot(BSPrim requestor) 132 public bool IsRoot(BSPhysObject requestor)
126 { 133 {
127 return (requestor.LocalID == m_linksetRoot.LocalID); 134 return (requestor.LocalID == m_linksetRoot.LocalID);
128 } 135 }
@@ -133,12 +140,12 @@ public class BSLinkset
133 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 140 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
134 141
135 // Return 'true' if this child is in this linkset 142 // Return 'true' if this child is in this linkset
136 public bool HasChild(BSPrim child) 143 public bool HasChild(BSPhysObject child)
137 { 144 {
138 bool ret = false; 145 bool ret = false;
139 lock (m_linksetActivityLock) 146 lock (m_linksetActivityLock)
140 { 147 {
141 foreach (BSPrim bp in m_children) 148 foreach (BSPhysObject bp in m_children)
142 { 149 {
143 if (child.LocalID == bp.LocalID) 150 if (child.LocalID == bp.LocalID)
144 { 151 {
@@ -153,7 +160,7 @@ public class BSLinkset
153 private float ComputeLinksetMass() 160 private float ComputeLinksetMass()
154 { 161 {
155 float mass = m_linksetRoot.MassRaw; 162 float mass = m_linksetRoot.MassRaw;
156 foreach (BSPrim bp in m_children) 163 foreach (BSPhysObject bp in m_children)
157 { 164 {
158 mass += bp.MassRaw; 165 mass += bp.MassRaw;
159 } 166 }
@@ -167,7 +174,7 @@ public class BSLinkset
167 174
168 lock (m_linksetActivityLock) 175 lock (m_linksetActivityLock)
169 { 176 {
170 foreach (BSPrim bp in m_children) 177 foreach (BSPhysObject bp in m_children)
171 { 178 {
172 com += bp.Position * bp.MassRaw; 179 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw; 180 totalMass += bp.MassRaw;
@@ -185,7 +192,7 @@ public class BSLinkset
185 192
186 lock (m_linksetActivityLock) 193 lock (m_linksetActivityLock)
187 { 194 {
188 foreach (BSPrim bp in m_children) 195 foreach (BSPhysObject bp in m_children)
189 { 196 {
190 com += bp.Position * bp.MassRaw; 197 com += bp.Position * bp.MassRaw;
191 } 198 }
@@ -197,7 +204,7 @@ public class BSLinkset
197 204
198 // When physical properties are changed the linkset needs to recalculate 205 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties. 206 // its internal properties.
200 public void Refresh(BSPrim requestor) 207 public void Refresh(BSPhysObject requestor)
201 { 208 {
202 // If there are no children, there aren't any constraints to recompute 209 // If there are no children, there aren't any constraints to recompute
203 if (!HasAnyChildren) 210 if (!HasAnyChildren)
@@ -223,10 +230,10 @@ public class BSLinkset
223 float linksetMass = LinksetMass; 230 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock) 231 lock (m_linksetActivityLock)
225 { 232 {
226 foreach (BSPrim child in m_children) 233 foreach (BSPhysObject child in m_children)
227 { 234 {
228 BSConstraint constrain; 235 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) 236 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
230 { 237 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", 238 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); 239 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
@@ -238,8 +245,8 @@ public class BSLinkset
238 // their constraints have not been created yet. 245 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints 246 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time. 247 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", 248 // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}",
242 // m_linksetRoot.Body.ID, child.Body.ID); 249 // LogHeader, m_linksetRoot.Body.ID, child.Body.ID);
243 } 250 }
244 } 251 }
245 } 252 }
@@ -248,18 +255,17 @@ public class BSLinkset
248 255
249 // I am the root of a linkset and a new child is being added 256 // I am the root of a linkset and a new child is being added
250 // Called while LinkActivity is locked. 257 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child) 258 private void AddChildToLinkset(BSPhysObject child)
252 { 259 {
253 if (!HasChild(child)) 260 if (!HasChild(child))
254 { 261 {
255 m_children.Add(child); 262 m_children.Add(child);
256 263
257 BSPrim rootx = LinksetRoot; // capture the root as of now 264 BSPhysObject rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child; 265 BSPhysObject childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate() 266 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
260 { 267 {
261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 268 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 269 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
264 }); 270 });
265 } 271 }
@@ -271,7 +277,7 @@ public class BSLinkset
271 // it's still connected to the linkset. 277 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 278 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent). 279 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild) 280 private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
275 { 281 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild); 282 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild); 283 RemoveChildFromLinkset(pchild);
@@ -279,16 +285,15 @@ public class BSLinkset
279 285
280 // I am the root of a linkset and one of my children is being removed. 286 // I am the root of a linkset and one of my children is being removed.
281 // Safe to call even if the child is not really in my linkset. 287 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child) 288 private void RemoveChildFromLinkset(BSPhysObject child)
283 { 289 {
284 if (m_children.Remove(child)) 290 if (m_children.Remove(child))
285 { 291 {
286 BSPrim rootx = LinksetRoot; // capture the root as of now 292 BSPhysObject rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child; 293 BSPhysObject childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 294 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
289 { 295 {
290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 296 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
292 297
293 PhysicallyUnlinkAChildFromRoot(rootx, childx); 298 PhysicallyUnlinkAChildFromRoot(rootx, childx);
294 }); 299 });
@@ -305,7 +310,7 @@ public class BSLinkset
305 310
306 // Create a constraint between me (root of linkset) and the passed prim (the child). 311 // Create a constraint between me (root of linkset) and the passed prim (the child).
307 // Called at taint time! 312 // Called at taint time!
308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) 313 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
309 { 314 {
310 // Zero motion for children so they don't interpolate 315 // Zero motion for children so they don't interpolate
311 childPrim.ZeroMotion(); 316 childPrim.ZeroMotion();
@@ -319,19 +324,18 @@ public class BSLinkset
319 324
320 // create a constraint that allows no freedom of movement between the two objects 325 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 326 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", 327 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); 328 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint( 329 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body, 330 m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody,
327 midPoint, 331 midPoint,
328 true, 332 true,
329 true 333 true
330 ); 334 );
331 /* NOTE: attempt to build constraint with full frame computation, etc. 335 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms 336 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects. 337 * of the objects.
334 * Code left here as an example. 338 * Code left as a warning to future programmers.
335 // ================================================================================== 339 // ==================================================================================
336 // relative position normalized to the root prim 340 // relative position normalized to the root prim
337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); 341 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
@@ -343,7 +347,6 @@ public class BSLinkset
343 347
344 // create a constraint that allows no freedom of movement between the two objects 348 // create a constraint that allows no freedom of movement between the two objects
345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 349 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 350 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
348 BS6DofConstraint constrain = new BS6DofConstraint( 351 BS6DofConstraint constrain = new BS6DofConstraint(
349 PhysicsScene.World, rootPrim.Body, childPrim.Body, 352 PhysicsScene.World, rootPrim.Body, childPrim.Body,
@@ -380,34 +383,24 @@ public class BSLinkset
380 383
381 // Remove linkage between myself and a particular child 384 // Remove linkage between myself and a particular child
382 // Called at taint time! 385 // Called at taint time!
383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) 386 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
384 { 387 {
385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 388 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
388 389
389 // Find the constraint for this link and get rid of it from the overall collection and from my list 390 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); 391 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody);
391 392
392 // Make the child refresh its location 393 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); 394 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr);
394 } 395 }
395 396
396 // Remove linkage between myself and any possible children I might have 397 // Remove linkage between myself and any possible children I might have
397 // Called at taint time! 398 // Called at taint time!
398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) 399 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
399 { 400 {
400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
402 402
403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); 403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
404 }
405
406 // Invoke the detailed logger and output something if it's enabled.
407 private void DebugLog(string msg, params Object[] args)
408 {
409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
411 } 404 }
412 405
413 // Invoke the detailed logger and output something if it's enabled. 406 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
new file mode 100755
index 0000000..e411fcb
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -0,0 +1,64 @@
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;
30
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37// Class to wrap all objects.
38// The rest of BulletSim doesn't need to keep checking for avatars or prims
39// unless the difference is significant.
40public abstract class BSPhysObject : PhysicsActor
41{
42 public abstract BSLinkset Linkset { get; set; }
43
44 public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
45 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
46 public abstract void SendCollisions();
47
48 // Return the object mass without calculating it or side effects
49 public abstract float MassRaw { get; }
50
51 // Reference to the physical body (btCollisionObject) of this object
52 public abstract BulletBody BSBody { get; set; }
53 // Reference to the physical shape (btCollisionShape) of this object
54 public abstract BulletShape BSShape { get; set; }
55
56 public abstract void ZeroMotion();
57
58 public virtual void StepVehicle(float timeStep) { }
59
60 public abstract void UpdateProperties(EntityProperties entprop);
61
62 public abstract void Destroy();
63}
64}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 9c20004..6d0af63 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -37,13 +37,11 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
37namespace OpenSim.Region.Physics.BulletSPlugin 37namespace OpenSim.Region.Physics.BulletSPlugin
38{ 38{
39 [Serializable] 39 [Serializable]
40public sealed class BSPrim : PhysicsActor 40public sealed class BSPrim : BSPhysObject
41{ 41{
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); }
46
47 private IMesh _mesh; 45 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 46 private PrimitiveBaseShape _pbs;
49 private ShapeData.PhysicsShapeType _shapeType; 47 private ShapeData.PhysicsShapeType _shapeType;
@@ -90,23 +88,16 @@ public sealed class BSPrim : PhysicsActor
90 private float _buoyancy; 88 private float _buoyancy;
91 89
92 // Membership in a linkset is controlled by this class. 90 // Membership in a linkset is controlled by this class.
93 private BSLinkset _linkset; 91 public override BSLinkset Linkset { get; set; }
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
99 92
100 private int _subscribedEventsMs = 0; 93 private int _subscribedEventsMs = 0;
101 private int _nextCollisionOkTime = 0; 94 private int _nextCollisionOkTime = 0;
102 long _collidingStep; 95 long _collidingStep;
103 long _collidingGroundStep; 96 long _collidingGroundStep;
97 CollisionFlags m_currentCollisionFlags = 0;
104 98
105 private BulletBody m_body; 99 public override BulletBody BSBody { get; set; }
106 public BulletBody Body { 100 public override BulletShape BSShape { get; set; }
107 get { return m_body; }
108 set { m_body = value; }
109 }
110 101
111 private BSDynamics _vehicle; 102 private BSDynamics _vehicle;
112 103
@@ -124,6 +115,7 @@ public sealed class BSPrim : PhysicsActor
124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 115 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
125 _localID = localID; 116 _localID = localID;
126 _avName = primName; 117 _avName = primName;
118 _physicsActorType = (int)ActorTypes.Prim;
127 _scene = parent_scene; 119 _scene = parent_scene;
128 _position = pos; 120 _position = pos;
129 _size = size; 121 _size = size;
@@ -141,8 +133,8 @@ public sealed class BSPrim : PhysicsActor
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 135 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 136 Linkset = new BSLinkset(Scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
146 _mass = CalculateMass(); 138 _mass = CalculateMass();
147 // do the actual object creation at taint time 139 // do the actual object creation at taint time
148 DetailLog("{0},BSPrim.constructor,call", LocalID); 140 DetailLog("{0},BSPrim.constructor,call", LocalID);
@@ -153,23 +145,25 @@ public sealed class BSPrim : PhysicsActor
153 // Get the pointer to the physical body for this object. 145 // Get the pointer to the physical body for this object.
154 // At the moment, we're still letting BulletSim manage the creation and destruction 146 // At the moment, we're still letting BulletSim manage the creation and destruction
155 // of the object. Someday we'll move that into the C# code. 147 // of the object. Someday we'll move that into the C# code.
156 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 148 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
149 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
150 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
157 }); 151 });
158 } 152 }
159 153
160 // called when this prim is being destroyed and we should free all the resources 154 // called when this prim is being destroyed and we should free all the resources
161 public void Destroy() 155 public override void Destroy()
162 { 156 {
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 157 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 158
165 // Undo any links between me and any other object 159 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot; 160 BSPhysObject parentBefore = Linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 161 int childrenBefore = Linkset.NumberOfChildren;
168 162
169 _linkset = _linkset.RemoveMeFromLinkset(this); 163 Linkset = Linkset.RemoveMeFromLinkset(this);
170 164
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 165 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 166 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
173 167
174 // Undo any vehicle properties 168 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 169 this.VehicleType = (int)Vehicle.TYPE_NONE;
@@ -193,7 +187,7 @@ public sealed class BSPrim : PhysicsActor
193 { 187 {
194 _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 190 DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
197 RecreateGeomAndObject(); 191 RecreateGeomAndObject();
198 }); 192 });
199 } 193 }
@@ -232,14 +226,13 @@ public sealed class BSPrim : PhysicsActor
232 BSPrim parent = obj as BSPrim; 226 BSPrim parent = obj as BSPrim;
233 if (parent != null) 227 if (parent != null)
234 { 228 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 229 BSPhysObject parentBefore = Linkset.LinksetRoot;
236 BSPrim parentBefore = _linkset.LinksetRoot; 230 int childrenBefore = Linkset.NumberOfChildren;
237 int childrenBefore = _linkset.NumberOfChildren;
238 231
239 _linkset = parent.Linkset.AddMeToLinkset(this); 232 Linkset = parent.Linkset.AddMeToLinkset(this);
240 233
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 234 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 235 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
243 } 236 }
244 return; 237 return;
245 } 238 }
@@ -248,16 +241,14 @@ public sealed class BSPrim : PhysicsActor
248 public override void delink() { 241 public override void delink() {
249 // TODO: decide if this parent checking needs to happen at taint time 242 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 243 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
253 244
254 BSPrim parentBefore = _linkset.LinksetRoot; 245 BSPhysObject parentBefore = Linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 246 int childrenBefore = Linkset.NumberOfChildren;
256 247
257 _linkset = _linkset.RemoveMeFromLinkset(this); 248 Linkset = Linkset.RemoveMeFromLinkset(this);
258 249
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 250 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 251 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
261 return; 252 return;
262 } 253 }
263 254
@@ -265,28 +256,28 @@ public sealed class BSPrim : PhysicsActor
265 // Do it to the properties so the values get set in the physics engine. 256 // Do it to the properties so the values get set in the physics engine.
266 // Push the setting of the values to the viewer. 257 // Push the setting of the values to the viewer.
267 // Called at taint time! 258 // Called at taint time!
268 public void ZeroMotion() 259 public override void ZeroMotion()
269 { 260 {
270 _velocity = OMV.Vector3.Zero; 261 _velocity = OMV.Vector3.Zero;
271 _acceleration = OMV.Vector3.Zero; 262 _acceleration = OMV.Vector3.Zero;
272 _rotationalVelocity = OMV.Vector3.Zero; 263 _rotationalVelocity = OMV.Vector3.Zero;
273 264
274 // Zero some other properties directly into the physics engine 265 // Zero some other properties directly into the physics engine
275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); 266 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); 267 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); 268 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
278 BulletSimAPI.ClearForces2(Body.Ptr); 269 BulletSimAPI.ClearForces2(BSBody.Ptr);
279 } 270 }
280 271
281 public override void LockAngularMotion(OMV.Vector3 axis) 272 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 273 {
283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 274 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 275 return;
285 } 276 }
286 277
287 public override OMV.Vector3 Position { 278 public override OMV.Vector3 Position {
288 get { 279 get {
289 if (!_linkset.IsRoot(this)) 280 if (!Linkset.IsRoot(this))
290 // child prims move around based on their parent. Need to get the latest location 281 // child prims move around based on their parent. Need to get the latest location
291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 282 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
292 283
@@ -299,7 +290,7 @@ public sealed class BSPrim : PhysicsActor
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 290 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 291 _scene.TaintedObject("BSPrim.setPosition", delegate()
301 { 292 {
302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 293 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 294 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
304 }); 295 });
305 } 296 }
@@ -311,23 +302,23 @@ public sealed class BSPrim : PhysicsActor
311 { 302 {
312 get 303 get
313 { 304 {
314 return _linkset.LinksetMass; 305 return Linkset.LinksetMass;
315 } 306 }
316 } 307 }
317 308
318 // used when we only want this prim's mass and not the linkset thing 309 // used when we only want this prim's mass and not the linkset thing
319 public float MassRaw { get { return _mass; } } 310 public override float MassRaw { get { return _mass; } }
320 311
321 // Is this used? 312 // Is this used?
322 public override OMV.Vector3 CenterOfMass 313 public override OMV.Vector3 CenterOfMass
323 { 314 {
324 get { return _linkset.CenterOfMass; } 315 get { return Linkset.CenterOfMass; }
325 } 316 }
326 317
327 // Is this used? 318 // Is this used?
328 public override OMV.Vector3 GeometricCenter 319 public override OMV.Vector3 GeometricCenter
329 { 320 {
330 get { return _linkset.GeometricCenter; } 321 get { return Linkset.GeometricCenter; }
331 } 322 }
332 323
333 public override OMV.Vector3 Force { 324 public override OMV.Vector3 Force {
@@ -336,9 +327,9 @@ public sealed class BSPrim : PhysicsActor
336 _force = value; 327 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 328 _scene.TaintedObject("BSPrim.setForce", delegate()
338 { 329 {
339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 330 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 331 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force); 332 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
342 }); 333 });
343 } 334 }
344 } 335 }
@@ -354,7 +345,7 @@ public sealed class BSPrim : PhysicsActor
354 { 345 {
355 // Done at taint time so we're sure the physics engine is not using the variables 346 // 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. 347 // Vehicle code changes the parameters for this vehicle type.
357 _vehicle.ProcessTypeChange(type); 348 _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep);
358 // Tell the scene about the vehicle so it will get processing each frame. 349 // Tell the scene about the vehicle so it will get processing each frame.
359 _scene.VehicleInSceneTypeChanged(this, type); 350 _scene.VehicleInSceneTypeChanged(this, type);
360 }); 351 });
@@ -391,7 +382,7 @@ public sealed class BSPrim : PhysicsActor
391 382
392 // Called each simulation step to advance vehicle characteristics. 383 // Called each simulation step to advance vehicle characteristics.
393 // Called from Scene when doing simulation step so we're in taint processing time. 384 // Called from Scene when doing simulation step so we're in taint processing time.
394 public void StepVehicle(float timeStep) 385 public override void StepVehicle(float timeStep)
395 { 386 {
396 if (IsPhysical) 387 if (IsPhysical)
397 _vehicle.Step(timeStep); 388 _vehicle.Step(timeStep);
@@ -414,7 +405,7 @@ public sealed class BSPrim : PhysicsActor
414 _velocity = value; 405 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 406 _scene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 407 {
417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 408 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 409 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
419 }); 410 });
420 } 411 }
@@ -422,7 +413,7 @@ public sealed class BSPrim : PhysicsActor
422 public override OMV.Vector3 Torque { 413 public override OMV.Vector3 Torque {
423 get { return _torque; } 414 get { return _torque; }
424 set { _torque = value; 415 set { _torque = value;
425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 416 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 417 }
427 } 418 }
428 public override float CollisionScore { 419 public override float CollisionScore {
@@ -436,7 +427,7 @@ public sealed class BSPrim : PhysicsActor
436 } 427 }
437 public override OMV.Quaternion Orientation { 428 public override OMV.Quaternion Orientation {
438 get { 429 get {
439 if (!_linkset.IsRoot(this)) 430 if (!Linkset.IsRoot(this))
440 { 431 {
441 // Children move around because tied to parent. Get a fresh value. 432 // Children move around because tied to parent. Get a fresh value.
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 433 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
@@ -449,15 +440,14 @@ public sealed class BSPrim : PhysicsActor
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 440 _scene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 441 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 442 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 443 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 444 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
454 }); 445 });
455 } 446 }
456 } 447 }
457 public override int PhysicsActorType { 448 public override int PhysicsActorType {
458 get { return _physicsActorType; } 449 get { return _physicsActorType; }
459 set { _physicsActorType = value; 450 set { _physicsActorType = value; }
460 }
461 } 451 }
462 public override bool IsPhysical { 452 public override bool IsPhysical {
463 get { return _isPhysical; } 453 get { return _isPhysical; }
@@ -484,30 +474,88 @@ public sealed class BSPrim : PhysicsActor
484 474
485 // Make gravity work if the object is physical and not selected 475 // Make gravity work if the object is physical and not selected
486 // No locking here because only called when it is safe 476 // No locking here because only called when it is safe
477 // There are four flags we're interested in:
478 // IsStatic: Object does not move, otherwise the object has mass and moves
479 // isSolid: other objects bounce off of this object
480 // isVolumeDetect: other objects pass through but can generate collisions
481 // collisionEvents: whether this object returns collision events
487 private void SetObjectDynamic() 482 private void SetObjectDynamic()
488 { 483 {
489 // RA: remove this for the moment. 484 // If it's becoming dynamic, it will need hullness
490 // The problem is that dynamic objects are hulls so if we are becoming physical 485 VerifyCorrectPhysicalShape();
491 // the shape has to be checked and possibly built.
492 // Maybe a VerifyCorrectPhysicalShape() routine?
493 // RecreateGeomAndObject();
494 486
495 // Bullet wants static objects to have a mass of zero 487 // Bullet wants static objects to have a mass of zero
496 float mass = IsStatic ? 0f : _mass; 488 float mass = IsStatic ? 0f : _mass;
497 489
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
491 /*
492 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
499 493
500 // recompute any linkset parameters 494 // Set up the object physicalness (static or dynamic)
501 _linkset.Refresh(this); 495 MakeDynamic();
502 496
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 497 // Make solid or not and arrange for collisions, etc
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 498 MakeSolid();
499
500 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
501
502 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
503 */
504
505 // Recompute any linkset parameters.
506 // When going from non-physical to physical, this re-enables the constraints that
507 // had been automatically disabled when the mass was set to zero.
508 Linkset.Refresh(this);
509
510 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags);
511 }
512
513 // "Making dynamic" means changing to and from static.
514 // When static, gravity does not effect the object and it is fixed in space.
515 // When dynamic, the object can fall and be pushed by others.
516 // This is independent of its 'solidness' which controls what passes through
517 // this object and what interacts with it.
518 private void MakeDynamic()
519 {
520 if (IsStatic)
521 {
522 // Become a Bullet 'static' object type
523 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
524 // Stop all movement
525 BulletSimAPI.ClearAllForces2(BSBody.Ptr);
526 // Mass is zero which disables a bunch of physics stuff in Bullet
527 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
528 // There is no inertia in a static object
529 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
530 // The activation state is 'sleeping' so Bullet will not try to act on it
531 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
532 }
533 else
534 {
535 // Not a Bullet static object
536 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
537 // A dynamic object has mass
538 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero);
539 // The shape is interesting and has mass and a center of gravity
540 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
541 BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero);
542 // Inertia is based on our new mass
543 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
544 // Force activation of the object so Bullet will act on it.
545 BulletSimAPI.Activate2(BSBody.Ptr, true);
546 }
547 }
548
549 private void MakeSolid()
550 {
505 } 551 }
506 552
507 // prims don't fly 553 // prims don't fly
508 public override bool Flying { 554 public override bool Flying {
509 get { return _flying; } 555 get { return _flying; }
510 set { _flying = value; } 556 set {
557 _flying = value;
558 }
511 } 559 }
512 public override bool SetAlwaysRun { 560 public override bool SetAlwaysRun {
513 get { return _setAlwaysRun; } 561 get { return _setAlwaysRun; }
@@ -558,7 +606,7 @@ public sealed class BSPrim : PhysicsActor
558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 606 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 607 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
560 { 608 {
561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 609 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 610 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
563 }); 611 });
564 } 612 }
@@ -575,7 +623,7 @@ public sealed class BSPrim : PhysicsActor
575 _buoyancy = value; 623 _buoyancy = value;
576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 624 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
577 { 625 {
578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 626 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 627 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
580 }); 628 });
581 } 629 }
@@ -624,7 +672,7 @@ public sealed class BSPrim : PhysicsActor
624 } 672 }
625 else 673 else
626 { 674 {
627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 675 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
628 return; 676 return;
629 } 677 }
630 _scene.TaintedObject("BSPrim.AddForce", delegate() 678 _scene.TaintedObject("BSPrim.AddForce", delegate()
@@ -638,17 +686,18 @@ public sealed class BSPrim : PhysicsActor
638 } 686 }
639 m_accumulatedForces.Clear(); 687 m_accumulatedForces.Clear();
640 } 688 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 689 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 690 // For unknown reason, "ApplyCentralForce" is really additive.
691 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
643 }); 692 });
644 } 693 }
645 694
646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 695 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 696 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 697 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
649 } 698 }
650 public override void SetMomentum(OMV.Vector3 momentum) { 699 public override void SetMomentum(OMV.Vector3 momentum) {
651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 700 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
652 } 701 }
653 public override void SubscribeEvents(int ms) { 702 public override void SubscribeEvents(int ms) {
654 _subscribedEventsMs = ms; 703 _subscribedEventsMs = ms;
@@ -659,7 +708,7 @@ public sealed class BSPrim : PhysicsActor
659 708
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() 709 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 { 710 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 711 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 }); 712 });
664 } 713 }
665 } 714 }
@@ -667,7 +716,7 @@ public sealed class BSPrim : PhysicsActor
667 _subscribedEventsMs = 0; 716 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() 717 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 { 718 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 719 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 }); 720 });
672 } 721 }
673 public override bool SubscribedEvents() { 722 public override bool SubscribedEvents() {
@@ -992,7 +1041,7 @@ public sealed class BSPrim : PhysicsActor
992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1041 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1042 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
994 { 1043 {
995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1044 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1045 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
997 // Bullet native objects are scaled by the Bullet engine so pass the size in 1046 // Bullet native objects are scaled by the Bullet engine so pass the size in
998 _scale = _size; 1047 _scale = _size;
@@ -1006,7 +1055,7 @@ public sealed class BSPrim : PhysicsActor
1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1055 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1056 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1008 { 1057 {
1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1058 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1059 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1011 _scale = _size; 1060 _scale = _size;
1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1061 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1042,19 +1091,26 @@ public sealed class BSPrim : PhysicsActor
1042 // No locking here because this is done when we know physics is not simulating 1091 // No locking here because this is done when we know physics is not simulating
1043 private void CreateGeomMesh() 1092 private void CreateGeomMesh()
1044 { 1093 {
1045 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1094 // level of detail based on size and type of the object
1095 float lod = _scene.MeshLOD;
1096 if (_pbs.SculptEntry)
1097 lod = _scene.SculptLOD;
1098 float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z));
1099 if (maxAxis > _scene.MeshMegaPrimThreshold)
1100 lod = _scene.MeshMegaPrimLOD;
1101
1046 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); 1102 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1047 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1103 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1048 1104
1049 // if this new shape is the same as last time, don't recreate the mesh 1105 // if this new shape is the same as last time, don't recreate the mesh
1050 if (_meshKey == newMeshKey) return; 1106 if (_meshKey == newMeshKey) return;
1051 1107
1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1108 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1053 // Since we're recreating new, get rid of any previously generated shape 1109 // Since we're recreating new, get rid of any previously generated shape
1054 if (_meshKey != 0) 1110 if (_meshKey != 0)
1055 { 1111 {
1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1112 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1113 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1114 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1059 _mesh = null; 1115 _mesh = null;
1060 _meshKey = 0; 1116 _meshKey = 0;
@@ -1084,7 +1140,7 @@ public sealed class BSPrim : PhysicsActor
1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1140 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1085 // meshes are already scaled by the meshmerizer 1141 // meshes are already scaled by the meshmerizer
1086 _scale = new OMV.Vector3(1f, 1f, 1f); 1142 _scale = new OMV.Vector3(1f, 1f, 1f);
1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1143 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1088 return; 1144 return;
1089 } 1145 }
1090 1146
@@ -1098,13 +1154,13 @@ public sealed class BSPrim : PhysicsActor
1098 // if the hull hasn't changed, don't rebuild it 1154 // if the hull hasn't changed, don't rebuild it
1099 if (newHullKey == _hullKey) return; 1155 if (newHullKey == _hullKey) return;
1100 1156
1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1157 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1102 1158
1103 // Since we're recreating new, get rid of any previously generated shape 1159 // Since we're recreating new, get rid of any previously generated shape
1104 if (_hullKey != 0) 1160 if (_hullKey != 0)
1105 { 1161 {
1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1162 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); 1163 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1164 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1109 _hullKey = 0; 1165 _hullKey = 0;
1110 } 1166 }
@@ -1198,7 +1254,7 @@ public sealed class BSPrim : PhysicsActor
1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1254 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1199 // meshes are already scaled by the meshmerizer 1255 // meshes are already scaled by the meshmerizer
1200 _scale = new OMV.Vector3(1f, 1f, 1f); 1256 _scale = new OMV.Vector3(1f, 1f, 1f);
1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1257 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1202 return; 1258 return;
1203 } 1259 }
1204 1260
@@ -1210,6 +1266,27 @@ public sealed class BSPrim : PhysicsActor
1210 return; 1266 return;
1211 } 1267 }
1212 1268
1269 private void VerifyCorrectPhysicalShape()
1270 {
1271 if (IsStatic)
1272 {
1273 // if static, we don't need a hull so, if there is one, rebuild without it
1274 if (_hullKey != 0)
1275 {
1276 RecreateGeomAndObject();
1277 }
1278 }
1279 else
1280 {
1281 // if not static, it will need a hull to efficiently collide with things
1282 if (_hullKey == 0)
1283 {
1284 RecreateGeomAndObject();
1285 }
1286
1287 }
1288 }
1289
1213 // Create an object in Bullet if it has not already been created 1290 // Create an object in Bullet if it has not already been created
1214 // No locking here because this is done when the physics engine is not simulating 1291 // No locking here because this is done when the physics engine is not simulating
1215 // Returns 'true' if an object was actually created. 1292 // Returns 'true' if an object was actually created.
@@ -1224,7 +1301,7 @@ public sealed class BSPrim : PhysicsActor
1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1301 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1225 1302
1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1303 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 1304 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1228 1305
1229 return ret; 1306 return ret;
1230 } 1307 }
@@ -1277,7 +1354,7 @@ public sealed class BSPrim : PhysicsActor
1277 const float ACCELERATION_TOLERANCE = 0.01f; 1354 const float ACCELERATION_TOLERANCE = 0.01f;
1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1355 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1279 1356
1280 public void UpdateProperties(EntityProperties entprop) 1357 public override void UpdateProperties(EntityProperties entprop)
1281 { 1358 {
1282 /* 1359 /*
1283 UpdatedProperties changed = 0; 1360 UpdatedProperties changed = 0;
@@ -1325,7 +1402,7 @@ public sealed class BSPrim : PhysicsActor
1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1402 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1326 1403
1327 // Updates only for individual prims and for the root object of a linkset. 1404 // Updates only for individual prims and for the root object of a linkset.
1328 if (_linkset.IsRoot(this)) 1405 if (Linkset.IsRoot(this))
1329 { 1406 {
1330 // Assign to the local variables so the normal set action does not happen 1407 // Assign to the local variables so the normal set action does not happen
1331 _position = entprop.Position; 1408 _position = entprop.Position;
@@ -1334,10 +1411,8 @@ public sealed class BSPrim : PhysicsActor
1334 _acceleration = entprop.Acceleration; 1411 _acceleration = entprop.Acceleration;
1335 _rotationalVelocity = entprop.RotationalVelocity; 1412 _rotationalVelocity = entprop.RotationalVelocity;
1336 1413
1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1414 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1415 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1341 1416
1342 base.RequestPhysicsterseUpdate(); 1417 base.RequestPhysicsterseUpdate();
1343 } 1418 }
@@ -1353,8 +1428,9 @@ public sealed class BSPrim : PhysicsActor
1353 } 1428 }
1354 1429
1355 // I've collided with something 1430 // I've collided with something
1431 // Called at taint time from within the Step() function
1356 CollisionEventUpdate collisionCollection; 1432 CollisionEventUpdate collisionCollection;
1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1433 public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1358 { 1434 {
1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1435 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
1360 1436
@@ -1367,8 +1443,14 @@ public sealed class BSPrim : PhysicsActor
1367 1443
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); 1444 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369 1445
1370 // if someone is subscribed to collision events.... 1446 // prims in the same linkset cannot collide with each other
1371 if (_subscribedEventsMs != 0) { 1447 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1448 {
1449 return;
1450 }
1451
1452 // if someone has subscribed for collision events....
1453 if (SubscribedEvents()) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription 1454 // throttle the collisions to the number of milliseconds specified in the subscription
1373 int nowTime = _scene.SimulationNowTime; 1455 int nowTime = _scene.SimulationNowTime;
1374 if (nowTime >= _nextCollisionOkTime) { 1456 if (nowTime >= _nextCollisionOkTime) {
@@ -1382,7 +1464,7 @@ public sealed class BSPrim : PhysicsActor
1382 } 1464 }
1383 1465
1384 // The scene is telling us it's time to pass our collected collisions into the simulator 1466 // The scene is telling us it's time to pass our collected collisions into the simulator
1385 public void SendCollisions() 1467 public override void SendCollisions()
1386 { 1468 {
1387 if (collisionCollection != null && collisionCollection.Count > 0) 1469 if (collisionCollection != null && collisionCollection.Count > 0)
1388 { 1470 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index a31c578..4a468af 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,8 +39,6 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Debug linkset
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 42// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties 43// Test sculpties
46// Compute physics FPS reasonably 44// Compute physics FPS reasonably
@@ -54,10 +52,8 @@ using OpenMetaverse;
54// Use collision masks for collision with terrain and phantom objects 52// Use collision masks for collision with terrain and phantom objects
55// Check out llVolumeDetect. Must do something for that. 53// Check out llVolumeDetect. Must do something for that.
56// Should prim.link() and prim.delink() membership checking happen at taint time? 54// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
61// Implement LockAngularMotion 57// Implement LockAngularMotion
62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
63// Does NeedsMeshing() really need to exclude all the different shapes? 59// Does NeedsMeshing() really need to exclude all the different shapes?
@@ -73,62 +69,61 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 69 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 70 private static readonly string LogHeader = "[BULLETS SCENE]";
75 71
76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } 72 // The name of the region we're working for.
73 public string RegionName { get; private set; }
77 74
78 public string BulletSimVersion = "?"; 75 public string BulletSimVersion = "?";
79 76
80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 77 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
81 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); 78
79 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
80 // Following is a kludge and can be removed when avatar animation updating is
81 // moved to a better place.
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); 82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
83 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>(); 83
84 private List<BSPrim> m_vehicles = new List<BSPrim>(); 84 // List of all the objects that have vehicle properties and should be called
85 private float[] m_heightMap; 85 // to update each physics step.
86 private float m_waterLevel; 86 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
87 private uint m_worldID;
88 public uint WorldID { get { return m_worldID; } }
89 87
90 // let my minuions use my logger 88 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } } 89 public ILog Logger { get { return m_log; } }
92 90
93 private bool m_initialized = false; 91 // If non-zero, the number of simulation steps between calls to the physics
94 92 // engine to output detailed physics stats. Debug logging level must be on also.
95 private int m_detailedStatsStep = 0; 93 private int m_detailedStatsStep = 0;
96 94
97 public IMesher mesher; 95 public IMesher mesher;
98 private float m_meshLOD; 96 // Level of Detail values kept as float because that's what the Meshmerizer wants
99 public float MeshLOD 97 public float MeshLOD { get; private set; }
100 { 98 public float MeshMegaPrimLOD { get; private set; }
101 get { return m_meshLOD; } 99 public float MeshMegaPrimThreshold { get; private set; }
102 } 100 public float SculptLOD { get; private set; }
103 private float m_sculptLOD;
104 public float SculptLOD
105 {
106 get { return m_sculptLOD; }
107 }
108 101
109 private BulletSim m_worldSim; 102 public uint WorldID { get; private set; }
110 public BulletSim World 103 public BulletSim World { get; private set; }
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119 104
105 // All the constraints that have been allocated in this instance.
106 public BSConstraintCollection Constraints { get; private set; }
107
108 // Simulation parameters
120 private int m_maxSubSteps; 109 private int m_maxSubSteps;
121 private float m_fixedTimeStep; 110 private float m_fixedTimeStep;
122 private long m_simulationStep = 0; 111 private long m_simulationStep = 0;
123 public long SimulationStep { get { return m_simulationStep; } } 112 public long SimulationStep { get { return m_simulationStep; } }
124 113
114 // The length of the last timestep we were asked to simulate.
115 // This is used by the vehicle code. Since the vehicle code is called
116 // once per simulation step, its constants need to be scaled by this.
125 public float LastSimulatedTimestep { get; private set; } 117 public float LastSimulatedTimestep { get; private set; }
126 118
127 // A value of the time now so all the collision and update routines do not have to get their own 119 // A value of the time now so all the collision and update routines do not have to get their own
128 // Set to 'now' just before all the prims and actors are called for collisions and updates 120 // Set to 'now' just before all the prims and actors are called for collisions and updates
129 private int m_simulationNowTime; 121 public int SimulationNowTime { get; private set; }
130 public int SimulationNowTime { get { return m_simulationNowTime; } } 122
123 // True if initialized and ready to do simulation steps
124 private bool m_initialized = false;
131 125
126 // Pinned memory used to pass step information between managed and unmanaged
132 private int m_maxCollisionsPerFrame; 127 private int m_maxCollisionsPerFrame;
133 private CollisionDesc[] m_collisionArray; 128 private CollisionDesc[] m_collisionArray;
134 private GCHandle m_collisionArrayPinnedHandle; 129 private GCHandle m_collisionArrayPinnedHandle;
@@ -145,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
145 140
146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 141 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
147 public const uint GROUNDPLANE_ID = 1; 142 public const uint GROUNDPLANE_ID = 1;
143 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
144
145 private float m_waterLevel;
146 public BSTerrainManager TerrainManager { get; private set; }
148 147
149 public ConfigurationParameters Params 148 public ConfigurationParameters Params
150 { 149 {
@@ -155,12 +154,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
155 get { return new Vector3(0f, 0f, Params.gravity); } 154 get { return new Vector3(0f, 0f, Params.gravity); }
156 } 155 }
157 156
158 private float m_maximumObjectMass; 157 public float MaximumObjectMass { get; private set; }
159 public float MaximumObjectMass
160 {
161 get { return m_maximumObjectMass; }
162 }
163 158
159 // When functions in the unmanaged code must be called, it is only
160 // done at a known time just before the simulation step. The taint
161 // system saves all these function calls and executes them in
162 // order before the simulation.
164 public delegate void TaintCallback(); 163 public delegate void TaintCallback();
165 private struct TaintCallbackEntry 164 private struct TaintCallbackEntry
166 { 165 {
@@ -176,11 +175,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
176 private Object _taintLock = new Object(); 175 private Object _taintLock = new Object();
177 176
178 // A pointer to an instance if this structure is passed to the C++ code 177 // A pointer to an instance if this structure is passed to the C++ code
178 // Used to pass basic configuration values to the unmanaged code.
179 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
180 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
181 181
182 public bool ShouldDebugLog { get; private set; } 182 // Handle to the callback used by the unmanaged code to call into the managed code.
183 183 // Used for debug logging.
184 // Need to store the handle in a persistant variable so it won't be freed.
184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 185 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
185 186
186 // Sometimes you just have to log everything. 187 // Sometimes you just have to log everything.
@@ -189,13 +190,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
189 private string m_physicsLoggingDir; 190 private string m_physicsLoggingDir;
190 private string m_physicsLoggingPrefix; 191 private string m_physicsLoggingPrefix;
191 private int m_physicsLoggingFileMinutes; 192 private int m_physicsLoggingFileMinutes;
193 // 'true' of the vehicle code is to log lots of details
194 public bool VehicleLoggingEnabled { get; private set; }
192 195
193 private bool m_vehicleLoggingEnabled; 196 #region Construction and Initialization
194 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
195
196 public BSScene(string identifier) 197 public BSScene(string identifier)
197 { 198 {
198 m_initialized = false; 199 m_initialized = false;
200 // we are passed the name of the region we're working for.
201 RegionName = identifier;
199 } 202 }
200 203
201 public override void Initialise(IMesher meshmerizer, IConfigSource config) 204 public override void Initialise(IMesher meshmerizer, IConfigSource config)
@@ -213,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
213 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 216 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
214 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 217 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
215 218
219 mesher = meshmerizer;
220 _taintedObjects = new List<TaintCallbackEntry>();
221
216 // Enable very detailed logging. 222 // Enable very detailed logging.
217 // By creating an empty logger when not logging, the log message invocation code 223 // By creating an empty logger when not logging, the log message invocation code
218 // can be left in and every call doesn't have to check for null. 224 // can be left in and every call doesn't have to check for null.
@@ -225,38 +231,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
225 PhysicsLogging = new Logging.LogWriter(); 231 PhysicsLogging = new Logging.LogWriter();
226 } 232 }
227 233
228 // Get the version of the DLL 234 // If Debug logging level, enable logging from the unmanaged code
229 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 235 m_DebugLogCallbackHandle = null;
230 // BulletSimVersion = BulletSimAPI.GetVersion();
231 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
232
233 // if Debug, enable logging from the unmanaged code
234 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 236 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
235 { 237 {
236 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 238 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
237 if (PhysicsLogging.Enabled) 239 if (PhysicsLogging.Enabled)
240 // The handle is saved in a variable to make sure it doesn't get freed after this call
238 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 241 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
239 else 242 else
240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 243 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
241 // the handle is saved in a variable to make sure it doesn't get freed after this call
242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
243 } 244 }
244 245
245 _taintedObjects = new List<TaintCallbackEntry>(); 246 // Get the version of the DLL
247 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
248 // BulletSimVersion = BulletSimAPI.GetVersion();
249 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
246 250
247 mesher = meshmerizer; 251 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
248 // The bounding box for the simulated world 252 // a child in a mega-region.
253 // Turns out that Bullet really doesn't care about the extents of the simulated
254 // area. It tracks active objects no matter where they are.
249 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 255 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
250 256
251 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 257 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
252 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 258 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
253 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 259 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
254 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 260 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
261 m_DebugLogCallbackHandle);
255 262
256 // Initialization to support the transition to a new API which puts most of the logic 263 // Initialization to support the transition to a new API which puts most of the logic
257 // into the C# code so it is easier to modify and add to. 264 // into the C# code so it is easier to modify and add to.
258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); 265 World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
259 m_constraintCollection = new BSConstraintCollection(World); 266
267 Constraints = new BSConstraintCollection(World);
268
269 TerrainManager = new BSTerrainManager(this);
270 TerrainManager.CreateInitialGroundPlaneAndTerrain();
260 271
261 m_initialized = true; 272 m_initialized = true;
262 } 273 }
@@ -281,10 +292,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
281 // Very detailed logging for physics debugging 292 // Very detailed logging for physics debugging
282 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 293 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
283 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 294 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
284 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); 295 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
285 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 296 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
286 // Very detailed logging for vehicle debugging 297 // Very detailed logging for vehicle debugging
287 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 298 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
299
300 // Do any replacements in the parameters
301 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
288 } 302 }
289 } 303 }
290 } 304 }
@@ -316,6 +330,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
316 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 330 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
317 } 331 }
318 332
333 public override void Dispose()
334 {
335 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
336
337 // make sure no stepping happens while we're deleting stuff
338 m_initialized = false;
339
340 TerrainManager.ReleaseGroundPlaneAndTerrain();
341
342 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
343 {
344 kvp.Value.Destroy();
345 }
346 PhysObjects.Clear();
347
348 // Now that the prims are all cleaned up, there should be no constraints left
349 if (Constraints != null)
350 {
351 Constraints.Dispose();
352 Constraints = null;
353 }
354
355 // Anything left in the unmanaged code should be cleaned out
356 BulletSimAPI.Shutdown(WorldID);
357
358 // Not logging any more
359 PhysicsLogging.Close();
360 }
361 #endregion // Construction and Initialization
362
363 #region Prim and Avatar addition and removal
364
319 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 365 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
320 { 366 {
321 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); 367 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -329,7 +375,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
329 if (!m_initialized) return null; 375 if (!m_initialized) return null;
330 376
331 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 377 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
332 lock (m_avatars) m_avatars.Add(localID, actor); 378 lock (PhysObjects) PhysObjects.Add(localID, actor);
379
380 // TODO: Remove kludge someday.
381 // We must generate a collision for avatars whether they collide or not.
382 // This is required by OpenSim to update avatar animations, etc.
383 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
384
333 return actor; 385 return actor;
334 } 386 }
335 387
@@ -344,7 +396,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
344 { 396 {
345 try 397 try
346 { 398 {
347 lock (m_avatars) m_avatars.Remove(actor.LocalID); 399 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
400 // Remove kludge someday
401 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
348 } 402 }
349 catch (Exception e) 403 catch (Exception e)
350 { 404 {
@@ -362,11 +416,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
362 BSPrim bsprim = prim as BSPrim; 416 BSPrim bsprim = prim as BSPrim;
363 if (bsprim != null) 417 if (bsprim != null)
364 { 418 {
365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID); 419 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 420 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
367 try 421 try
368 { 422 {
369 lock (m_prims) m_prims.Remove(bsprim.LocalID); 423 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
370 } 424 }
371 catch (Exception e) 425 catch (Exception e)
372 { 426 {
@@ -388,10 +442,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
388 442
389 if (!m_initialized) return null; 443 if (!m_initialized) return null;
390 444
391 // DetailLog("{0},AddPrimShape,call", localID); 445 DetailLog("{0},AddPrimShape,call", localID);
392 446
393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 447 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
394 lock (m_prims) m_prims.Add(localID, prim); 448 lock (PhysObjects) PhysObjects.Add(localID, prim);
395 return prim; 449 return prim;
396 } 450 }
397 451
@@ -400,6 +454,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 // information call is not needed. 454 // information call is not needed.
401 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 455 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
402 456
457 #endregion // Prim and Avatar addition and removal
458
459 #region Simulation
403 // Simulate one timestep 460 // Simulate one timestep
404 public override float Simulate(float timeStep) 461 public override float Simulate(float timeStep)
405 { 462 {
@@ -416,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
416 int simulateStartTime = Util.EnvironmentTickCount(); 473 int simulateStartTime = Util.EnvironmentTickCount();
417 474
418 // update the prim states while we know the physics engine is not busy 475 // update the prim states while we know the physics engine is not busy
476 int numTaints = _taintedObjects.Count;
419 ProcessTaints(); 477 ProcessTaints();
420 478
421 // Some of the prims operate with special vehicle properties 479 // Some of the prims operate with special vehicle properties
@@ -427,15 +485,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
427 int numSubSteps = 0; 485 int numSubSteps = 0;
428 try 486 try
429 { 487 {
430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 488 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 489 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 490 DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
491 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
433 } 492 }
434 catch (Exception e) 493 catch (Exception e)
435 { 494 {
436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 495 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 496 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
438 // updatedEntityCount = 0; 497 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
498 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
499 updatedEntityCount = 0;
439 collidersCount = 0; 500 collidersCount = 0;
440 } 501 }
441 502
@@ -443,7 +504,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
443 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 504 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
444 505
445 // Get a value for 'now' so all the collision and update routines don't have to get their own 506 // Get a value for 'now' so all the collision and update routines don't have to get their own
446 m_simulationNowTime = Util.EnvironmentTickCount(); 507 SimulationNowTime = Util.EnvironmentTickCount();
447 508
448 // If there were collisions, process them by sending the event to the prim. 509 // If there were collisions, process them by sending the event to the prim.
449 // Collisions must be processed before updates. 510 // Collisions must be processed before updates.
@@ -462,19 +523,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
462 523
463 // The above SendCollision's batch up the collisions on the objects. 524 // The above SendCollision's batch up the collisions on the objects.
464 // Now push the collisions into the simulator. 525 // Now push the collisions into the simulator.
465 foreach (BSPrim bsp in m_primsWithCollisions) 526 foreach (BSPhysObject bsp in m_objectsWithCollisions)
466 bsp.SendCollisions(); 527 bsp.SendCollisions();
467 m_primsWithCollisions.Clear(); 528 m_objectsWithCollisions.Clear();
468 529
469 // This is a kludge to get avatar movement updated. 530 // This is a kludge to get avatar movement updated.
470 // Don't send collisions only if there were collisions -- send everytime.
471 // ODE sends collisions even if there are none and this is used to update 531 // ODE sends collisions even if there are none and this is used to update
472 // avatar animations and stuff. 532 // avatar animations and stuff.
473 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 533 foreach (BSPhysObject bpo in m_avatarsWithCollisions)
474 // bsc.SendCollisions(); 534 bpo.SendCollisions();
475 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 535 // m_avatarsWithCollisions.Clear();
476 kvp.Value.SendCollisions();
477 m_avatarsWithCollisions.Clear();
478 536
479 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 537 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
480 if (updatedEntityCount > 0) 538 if (updatedEntityCount > 0)
@@ -482,16 +540,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
482 for (int ii = 0; ii < updatedEntityCount; ii++) 540 for (int ii = 0; ii < updatedEntityCount; ii++)
483 { 541 {
484 EntityProperties entprop = m_updateArray[ii]; 542 EntityProperties entprop = m_updateArray[ii];
485 BSPrim prim; 543 BSPhysObject pobj;
486 if (m_prims.TryGetValue(entprop.ID, out prim)) 544 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
487 { 545 {
488 prim.UpdateProperties(entprop); 546 pobj.UpdateProperties(entprop);
489 continue;
490 }
491 BSCharacter actor;
492 if (m_avatars.TryGetValue(entprop.ID, out actor))
493 {
494 actor.UpdateProperties(entprop);
495 continue; 547 continue;
496 } 548 }
497 } 549 }
@@ -521,56 +573,47 @@ public class BSScene : PhysicsScene, IPhysicsParameters
521 } 573 }
522 574
523 // Something has collided 575 // Something has collided
524 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) 576 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
525 { 577 {
526 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) 578 if (localID <= TerrainManager.HighestTerrainID)
527 { 579 {
528 return; // don't send collisions to the terrain 580 return; // don't send collisions to the terrain
529 } 581 }
530 582
583 BSPhysObject collider = PhysObjects[localID];
584 // TODO: as of this code, terrain was not in the physical object list.
585 // When BSTerrain is created and it will be in the list, we can remove
586 // the possibility that it's not there and just fetch the collidee.
587 BSPhysObject collidee = null;
588
531 ActorTypes type = ActorTypes.Prim; 589 ActorTypes type = ActorTypes.Prim;
532 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) 590 if (collidingWith <= TerrainManager.HighestTerrainID)
591 {
533 type = ActorTypes.Ground; 592 type = ActorTypes.Ground;
534 else if (m_avatars.ContainsKey(collidingWith))
535 type = ActorTypes.Agent;
536
537 BSPrim prim;
538 if (m_prims.TryGetValue(localID, out prim)) {
539 prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
540 m_primsWithCollisions.Add(prim);
541 return;
542 } 593 }
543 BSCharacter actor; 594 else
544 if (m_avatars.TryGetValue(localID, out actor)) { 595 {
545 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 596 collidee = PhysObjects[collidingWith];
546 m_avatarsWithCollisions.Add(actor); 597 if (collidee is BSCharacter)
547 return; 598 type = ActorTypes.Agent;
548 } 599 }
600
601 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
602
603 collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
604 m_objectsWithCollisions.Add(collider);
605
549 return; 606 return;
550 } 607 }
551 608
552 public override void GetResults() { } 609 #endregion // Simulation
553 610
554 public override void SetTerrain(float[] heightMap) { 611 public override void GetResults() { }
555 m_heightMap = heightMap;
556 this.TaintedObject("BSScene.SetTerrain", delegate()
557 {
558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
559 });
560 }
561 612
562 // Someday we will have complex terrain with caves and tunnels 613 #region Terrain
563 // For the moment, it's flat and convex
564 public float GetTerrainHeightAtXYZ(Vector3 loc)
565 {
566 return GetTerrainHeightAtXY(loc.X, loc.Y);
567 }
568 614
569 public float GetTerrainHeightAtXY(float tX, float tY) 615 public override void SetTerrain(float[] heightMap) {
570 { 616 TerrainManager.SetTerrain(heightMap);
571 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
572 return 30;
573 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
574 } 617 }
575 618
576 public override void SetWaterLevel(float baseheight) 619 public override void SetWaterLevel(float baseheight)
@@ -588,39 +631,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
588 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 631 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
589 } 632 }
590 633
591 public override void Dispose() 634 // Although no one seems to check this, I do support combining.
635 public override bool SupportsCombining()
592 { 636 {
593 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 637 return TerrainManager.SupportsCombining();
594 638 }
595 // make sure no stepping happens while we're deleting stuff 639 // This call says I am a child to region zero in a mega-region. 'pScene' is that
596 m_initialized = false; 640 // of region zero, 'offset' is my offset from regions zero's origin, and
597 641 // 'extents' is the largest XY that is handled in my region.
598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 642 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
599 { 643 {
600 kvp.Value.Destroy(); 644 TerrainManager.Combine(pScene, offset, extents);
601 } 645 }
602 m_avatars.Clear();
603
604 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
605 {
606 kvp.Value.Destroy();
607 }
608 m_prims.Clear();
609
610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
612 {
613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
615 }
616
617 // Anything left in the unmanaged code should be cleaned out
618 BulletSimAPI.Shutdown(WorldID);
619 646
620 // Not logging any more 647 // Unhook all the combining that I know about.
621 PhysicsLogging.Close(); 648 public override void UnCombine(PhysicsScene pScene)
649 {
650 TerrainManager.UnCombine(pScene);
622 } 651 }
623 652
653 #endregion // Terrain
654
624 public override Dictionary<uint, float> GetTopColliders() 655 public override Dictionary<uint, float> GetTopColliders()
625 { 656 {
626 return new Dictionary<uint, float>(); 657 return new Dictionary<uint, float>();
@@ -830,14 +861,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
830 // no locking because only called when physics engine is not busy 861 // no locking because only called when physics engine is not busy
831 private void ProcessVehicles(float timeStep) 862 private void ProcessVehicles(float timeStep)
832 { 863 {
833 foreach (BSPrim prim in m_vehicles) 864 foreach (BSPhysObject pobj in m_vehicles)
834 { 865 {
835 prim.StepVehicle(timeStep); 866 pobj.StepVehicle(timeStep);
836 } 867 }
837 } 868 }
838 #endregion Vehicles 869 #endregion Vehicles
839 870
840 #region Parameters 871 #region INI and command line parameter processing
841 872
842 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 873 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
843 delegate float ParamGet(BSScene scene); 874 delegate float ParamGet(BSScene scene);
@@ -897,16 +928,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
897 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 928 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
898 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 929 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
899 930
900 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 931 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
901 8f, 932 8f,
902 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, 933 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
903 (s) => { return (float)s.m_meshLOD; }, 934 (s) => { return s.MeshLOD; },
904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 935 (s,p,l,v) => { s.MeshLOD = v; } ),
905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 936 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
937 16f,
938 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
939 (s) => { return s.MeshMegaPrimLOD; },
940 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
941 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
942 10f,
943 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
944 (s) => { return s.MeshMegaPrimThreshold; },
945 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
946 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
906 32f, 947 32f,
907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 948 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
908 (s) => { return (float)s.m_sculptLOD; }, 949 (s) => { return s.SculptLOD; },
909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 950 (s,p,l,v) => { s.SculptLOD = v; } ),
910 951
911 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 952 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
912 10f, 953 10f,
@@ -930,9 +971,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
930 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 971 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
931 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 972 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
932 10000.01f, 973 10000.01f,
933 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, 974 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
934 (s) => { return (float)s.m_maximumObjectMass; }, 975 (s) => { return (float)s.MaximumObjectMass; },
935 (s,p,l,v) => { s.m_maximumObjectMass = v; } ), 976 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
936 977
937 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 978 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
938 2200f, 979 2200f,
@@ -976,42 +1017,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
976 0f, 1017 0f,
977 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 1018 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].linearDamping; }, 1019 (s) => { return s.m_params[0].linearDamping; },
979 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), 1020 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
980 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 1021 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
981 0f, 1022 0f,
982 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 1023 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].angularDamping; }, 1024 (s) => { return s.m_params[0].angularDamping; },
984 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), 1025 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
985 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 1026 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
986 0.2f, 1027 0.2f,
987 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 1028 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].deactivationTime; }, 1029 (s) => { return s.m_params[0].deactivationTime; },
989 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), 1030 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
990 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 1031 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
991 0.8f, 1032 0.8f,
992 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 1033 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
993 (s) => { return s.m_params[0].linearSleepingThreshold; }, 1034 (s) => { return s.m_params[0].linearSleepingThreshold; },
994 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 1035 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
995 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1036 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
996 1.0f, 1037 1.0f,
997 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 1038 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].angularSleepingThreshold; }, 1039 (s) => { return s.m_params[0].angularSleepingThreshold; },
999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 1040 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
1000 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 1041 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1001 0f, // set to zero to disable 1042 0f, // set to zero to disable
1002 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1043 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1044 (s) => { return s.m_params[0].ccdMotionThreshold; },
1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 1045 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
1005 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1046 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1006 0f, 1047 0f,
1007 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1048 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1049 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 1050 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1051 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1011 0.1f, 1052 0.1f,
1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1053 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1054 (s) => { return s.m_params[0].contactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 1055 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
1015 1056
1016 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1057 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1017 0.5f, 1058 0.5f,
@@ -1029,35 +1070,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1029 (s) => { return s.m_params[0].terrainRestitution; }, 1070 (s) => { return s.m_params[0].terrainRestitution; },
1030 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1071 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
1031 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1072 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1032 0.5f, 1073 0.2f,
1033 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1074 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1034 (s) => { return s.m_params[0].avatarFriction; }, 1075 (s) => { return s.m_params[0].avatarFriction; },
1035 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), 1076 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1036 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1077 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1037 60f, 1078 60f,
1038 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1079 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1039 (s) => { return s.m_params[0].avatarDensity; }, 1080 (s) => { return s.m_params[0].avatarDensity; },
1040 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), 1081 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1041 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 1082 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1042 0f, 1083 0f,
1043 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1084 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].avatarRestitution; }, 1085 (s) => { return s.m_params[0].avatarRestitution; },
1045 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1086 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1046 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1087 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1047 0.37f, 1088 0.37f,
1048 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1089 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1090 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1050 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1091 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1051 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1092 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1052 1.5f, 1093 1.5f,
1053 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1094 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1054 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 1095 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 1096 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1056 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 1097 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1057 0.1f, 1098 0.1f,
1058 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 1099 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1059 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1100 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1101 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1061 1102
1062 1103
1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1104 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
@@ -1137,12 +1178,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1137 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, 1178 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1138 (s) => { return (float)s.m_detailedStatsStep; }, 1179 (s) => { return (float)s.m_detailedStatsStep; },
1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1180 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1141 ConfigurationParameters.numericFalse,
1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1145
1146 }; 1181 };
1147 1182
1148 // Convert a boolean to our numeric true and false values 1183 // Convert a boolean to our numeric true and false values
@@ -1200,6 +1235,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1200 1235
1201 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1236 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1202 1237
1238 // This creates an array in the correct format for returning the list of
1239 // parameters. This is used by the 'list' option of the 'physics' command.
1203 private void BuildParameterTable() 1240 private void BuildParameterTable()
1204 { 1241 {
1205 if (SettableParameters.Length < ParameterDefinitions.Length) 1242 if (SettableParameters.Length < ParameterDefinitions.Length)
@@ -1250,18 +1287,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1250 } 1287 }
1251 1288
1252 // check to see if we are updating a parameter for a particular or all of the prims 1289 // check to see if we are updating a parameter for a particular or all of the prims
1253 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1290 protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
1254 {
1255 List<uint> operateOn;
1256 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
1257 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1258 }
1259
1260 // check to see if we are updating a parameter for a particular or all of the avatars
1261 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
1262 { 1291 {
1263 List<uint> operateOn; 1292 List<uint> operateOn;
1264 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1293 lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
1265 UpdateParameterSet(operateOn, ref loc, parm, localID, val); 1294 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1266 } 1295 }
1267 1296
@@ -1284,7 +1313,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1284 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1313 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1285 foreach (uint lID in objectIDs) 1314 foreach (uint lID in objectIDs)
1286 { 1315 {
1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1316 BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
1288 } 1317 }
1289 }); 1318 });
1290 break; 1319 break;
@@ -1302,7 +1331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1302 string xparm = parm.ToLower(); 1331 string xparm = parm.ToLower();
1303 float xval = val; 1332 float xval = val;
1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1333 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1334 BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
1306 }); 1335 });
1307 } 1336 }
1308 1337
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
new file mode 100755
index 0000000..47d7199
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -0,0 +1,464 @@
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;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public class BSTerrainManager
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
46
47 // These height values are fractional so the odd values will be
48 // noticable when debugging.
49 public const float HEIGHT_INITIALIZATION = 24.987f;
50 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
51 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
52
53 // If the min and max height are equal, we reduce the min by this
54 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56
57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
61
62 // The scene that I am part of
63 private BSScene m_physicsScene;
64
65 // The ground plane created to keep thing from falling to infinity.
66 private BulletBody m_groundPlane;
67
68 // If doing mega-regions, if we're region zero we will be managing multiple
69 // region terrains since region zero does the physics for the whole mega-region.
70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
71
72 // True of the terrain has been modified.
73 // Used to force recalculation of terrain height after terrain has been modified
74 private bool m_terrainModified;
75
76 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
77 // This is incremented before assigning to new region so it is the last ID allocated.
78 private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
79 public uint HighestTerrainID { get {return m_terrainCount; } }
80
81 // If doing mega-regions, this holds our offset from region zero of
82 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
83 private Vector3 m_worldOffset;
84 // If the parent region (region 0), this is the extent of the combined regions
85 // relative to the origin of region zero
86 private Vector3 m_worldMax;
87 private PhysicsScene m_parentScene;
88
89 public BSTerrainManager(BSScene physicsScene)
90 {
91 m_physicsScene = physicsScene;
92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
93 m_terrainModified = false;
94
95 // Assume one region of default size
96 m_worldOffset = Vector3.Zero;
97 m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
98 m_parentScene = null;
99 }
100
101 // Create the initial instance of terrain and the underlying ground plane.
102 // The objects are allocated in the unmanaged space and the pointers are tracked
103 // by the managed code.
104 // The terrains and the groundPlane are not added to the list of PhysObjects.
105 // This is called from the initialization routine so we presume it is
106 // safe to call Bullet in real time. We hope no one is moving prims around yet.
107 public void CreateInitialGroundPlaneAndTerrain()
108 {
109 // The ground plane is here to catch things that are trying to drop to negative infinity
110 BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
111 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
112 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
113 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
114
115 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
116 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
117 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
118 float[] initialMap = new float[totalHeights];
119 for (int ii = 0; ii < totalHeights; ii++)
120 {
121 initialMap[ii] = HEIGHT_INITIALIZATION;
122 }
123 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
124 }
125
126 // Release all the terrain structures we might have allocated
127 public void ReleaseGroundPlaneAndTerrain()
128 {
129 if (m_groundPlane.Ptr != IntPtr.Zero)
130 {
131 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
132 {
133 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
134 }
135 m_groundPlane.Ptr = IntPtr.Zero;
136 }
137
138 ReleaseTerrain();
139 }
140
141 // Release all the terrain we have allocated
142 public void ReleaseTerrain()
143 {
144 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
145 {
146 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
147 {
148 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
149 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
150 }
151 }
152 m_heightMaps.Clear();
153 }
154
155 // The simulator wants to set a new heightmap for the terrain.
156 public void SetTerrain(float[] heightMap) {
157 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
158 {
159 // If a child of a mega-region, we shouldn't have any terrain allocated for us
160 ReleaseGroundPlaneAndTerrain();
161 // If doing the mega-prim stuff and we are the child of the zero region,
162 // the terrain is added to our parent
163 if (m_parentScene is BSScene)
164 {
165 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
166 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
167 ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
168 heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
169 }
170 }
171 else
172 {
173 // If not doing the mega-prim thing, just change the terrain
174 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
175
176 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
177 }
178 }
179
180 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
181 // based on the passed information. The 'id' should be either the terrain id or
182 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
183 // The latter feature is for creating child terrains for mega-regions.
184 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
185 // then a new body and shape is created and the mapInfo is filled.
186 // This call is used for doing the initial terrain creation.
187 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
188 // terrain shape is created and added to the body.
189 // This call is most often used to update the heightMap and parameters of the terrain.
190 // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
191 // calling this routine from initialization or taint-time routines) or whether to delay
192 // all the unmanaged activities to taint-time.
193 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
194 {
195 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
196 BSScene.DetailLogZero, minCoords, maxCoords, doNow);
197
198 float minZ = float.MaxValue;
199 float maxZ = float.MinValue;
200 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
201
202 int heightMapSize = heightMap.Length;
203 for (int ii = 0; ii < heightMapSize; ii++)
204 {
205 float height = heightMap[ii];
206 if (height < minZ) minZ = height;
207 if (height > maxZ) maxZ = height;
208 }
209
210 // The shape of the terrain is from its base to its extents.
211 minCoords.Z = minZ;
212 maxCoords.Z = maxZ;
213
214 BulletHeightMapInfo mapInfo;
215 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
216 {
217 // If this is terrain we know about, it's easy to update
218
219 mapInfo.heightMap = heightMap;
220 mapInfo.minCoords = minCoords;
221 mapInfo.maxCoords = maxCoords;
222 mapInfo.minZ = minZ;
223 mapInfo.maxZ = maxZ;
224 mapInfo.sizeX = maxCoords.X - minCoords.X;
225 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
226 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
227 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
228
229 BSScene.TaintCallback rebuildOperation = delegate()
230 {
231 if (m_parentScene != null)
232 {
233 // It's possible that Combine() was called after this code was queued.
234 // If we are a child of combined regions, we don't create any terrain for us.
235 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
236
237 // Get rid of any terrain that may have been allocated for us.
238 ReleaseGroundPlaneAndTerrain();
239
240 // I hate doing this, but just bail
241 return;
242 }
243
244 if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
245 {
246 // Updating an existing terrain.
247 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
248 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
249
250 // Remove from the dynamics world because we're going to mangle this object
251 BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
252
253 // Get rid of the old terrain
254 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
255 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
256 mapInfo.Ptr = IntPtr.Zero;
257
258 /*
259 // NOTE: This routine is half here because I can't get the terrain shape replacement
260 // to work. In the short term, the above three lines completely delete the old
261 // terrain and the code below recreates one from scratch.
262 // Hopefully the Bullet community will help me out on this one.
263
264 // First, release the old collision shape (there is only one terrain)
265 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
266
267 // Fill the existing height map info with the new location and size information
268 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
269 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
270
271 // Create a terrain shape based on the new info
272 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
273
274 // Stuff the shape into the existing terrain body
275 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
276 */
277 }
278 // else
279 {
280 // Creating a new terrain.
281 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
282 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
283
284 mapInfo.ID = id;
285 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
286 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
287
288 // The terrain object initial position is at the center of the object
289 Vector3 centerPos;
290 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
291 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
292 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
293
294 // Create the terrain shape from the mapInfo
295 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
296
297 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
298 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
299 centerPos, Quaternion.Identity));
300 }
301
302 // Make sure the entry is in the heightmap table
303 m_heightMaps[terrainRegionBase] = mapInfo;
304
305 // Set current terrain attributes
306 BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
307 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
308 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
309 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
310
311 BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
312 BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
313
314 // Return the new terrain to the world of physical objects
315 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
316
317 // redo its bounding box now that it is in the world
318 BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
319
320 // Make sure the new shape is processed.
321 BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
322 };
323
324 // There is the option to do the changes now (we're already in 'taint time'), or
325 // to do the Bullet operations later.
326 if (doNow)
327 rebuildOperation();
328 else
329 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
330 }
331 else
332 {
333 // We don't know about this terrain so either we are creating a new terrain or
334 // our mega-prim child is giving us a new terrain to add to the phys world
335
336 // if this is a child terrain, calculate a unique terrain id
337 uint newTerrainID = id;
338 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
339 newTerrainID = ++m_terrainCount;
340
341 float[] heightMapX = heightMap;
342 Vector3 minCoordsX = minCoords;
343 Vector3 maxCoordsX = maxCoords;
344
345 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
346 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
347
348 // Code that must happen at taint-time
349 BSScene.TaintCallback createOperation = delegate()
350 {
351 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
352 // Create a new mapInfo that will be filled with the new info
353 mapInfo = new BulletHeightMapInfo(id, heightMapX,
354 BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
355 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
356 // Put the unfilled heightmap info into the collection of same
357 m_heightMaps.Add(terrainRegionBase, mapInfo);
358 // Build the terrain
359 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
360 };
361
362 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
363 if (doNow)
364 createOperation();
365 else
366 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
367 }
368 }
369
370 // Someday we will have complex terrain with caves and tunnels
371 public float GetTerrainHeightAtXYZ(Vector3 loc)
372 {
373 // For the moment, it's flat and convex
374 return GetTerrainHeightAtXY(loc.X, loc.Y);
375 }
376
377 // Given an X and Y, find the height of the terrain.
378 // Since we could be handling multiple terrains for a mega-region,
379 // the base of the region is calcuated assuming all regions are
380 // the same size and that is the default.
381 // Once the heightMapInfo is found, we have all the information to
382 // compute the offset into the array.
383 private float lastHeightTX = 999999f;
384 private float lastHeightTY = 999999f;
385 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
386 public float GetTerrainHeightAtXY(float tX, float tY)
387 {
388 // You'd be surprized at the number of times this routine is called
389 // with the same parameters as last time.
390 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
391 return lastHeight;
392
393 lastHeightTX = tX;
394 lastHeightTY = tY;
395 float ret = HEIGHT_GETHEIGHT_RET;
396
397 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
398 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
399 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
400
401 BulletHeightMapInfo mapInfo;
402 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
403 {
404 float regionX = tX - offsetX;
405 float regionY = tY - offsetY;
406 if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0;
407 if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0;
408 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
409 ret = mapInfo.heightMap[mapIndex];
410 m_terrainModified = false;
411 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
412 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
413 }
414 else
415 {
416 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
417 LogHeader, m_physicsScene.RegionName, tX, tY);
418 }
419 lastHeight = ret;
420 return ret;
421 }
422
423 // Although no one seems to check this, I do support combining.
424 public bool SupportsCombining()
425 {
426 return true;
427 }
428
429 // This routine is called two ways:
430 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
431 // extent of the combined regions. This is to inform the parent of the size
432 // of the combined regions.
433 // and one with 'offset' as the offset of the child region to the base region,
434 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
435 // child of its relative base and new parent.
436 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
437 {
438 m_worldOffset = offset;
439 m_worldMax = extents;
440 m_parentScene = pScene;
441 if (pScene != null)
442 {
443 // We are a child.
444 // We want m_worldMax to be the highest coordinate of our piece of terrain.
445 m_worldMax = offset + DefaultRegionSize;
446 }
447 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
448 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
449 }
450
451 // Unhook all the combining that I know about.
452 public void UnCombine(PhysicsScene pScene)
453 {
454 // Just like ODE, for the moment a NOP
455 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
456 }
457
458
459 private void DetailLog(string msg, params Object[] args)
460 {
461 m_physicsScene.PhysicsLogging.Write(msg, args);
462 }
463}
464}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 504bd3c..e579cf2 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,15 +33,25 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36// These hold pointers to allocated objects in the unmanaged space.
37
38// The physics engine controller class created at initialization
36public struct BulletSim 39public struct BulletSim
37{ 40{
38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } 41 public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
39 public uint ID; 42 public uint worldID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages 43 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene; 44 public BSScene scene;
42 public IntPtr Ptr; 45 public IntPtr Ptr;
43} 46}
44 47
48public struct BulletShape
49{
50 public BulletShape(IntPtr xx) { Ptr = xx; }
51 public IntPtr Ptr;
52}
53
54// An allocated Bullet btRigidBody
45public struct BulletBody 55public struct BulletBody
46{ 56{
47 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } 57 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
@@ -49,12 +59,41 @@ public struct BulletBody
49 public uint ID; 59 public uint ID;
50} 60}
51 61
62// An allocated Bullet btConstraint
52public struct BulletConstraint 63public struct BulletConstraint
53{ 64{
54 public BulletConstraint(IntPtr xx) { Ptr = xx; } 65 public BulletConstraint(IntPtr xx) { Ptr = xx; }
55 public IntPtr Ptr; 66 public IntPtr Ptr;
56} 67}
57 68
69// An allocated HeightMapThing which hold various heightmap info
70// Made a class rather than a struct so there would be only one
71// instance of this and C# will pass around pointers rather
72// than making copies.
73public class BulletHeightMapInfo
74{
75 public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
76 ID = id;
77 Ptr = xx;
78 heightMap = hm;
79 terrainRegionBase = new Vector2(0f, 0f);
80 minCoords = new Vector3(100f, 100f, 25f);
81 maxCoords = new Vector3(101f, 101f, 26f);
82 minZ = maxZ = 0f;
83 sizeX = sizeY = 256f;
84 }
85 public uint ID;
86 public IntPtr Ptr;
87 public float[] heightMap;
88 public Vector2 terrainRegionBase;
89 public Vector3 minCoords;
90 public Vector3 maxCoords;
91 public float sizeX, sizeY;
92 public float minZ, maxZ;
93 public BulletShape terrainShape;
94 public BulletBody terrainBody;
95}
96
58// =============================================================================== 97// ===============================================================================
59[StructLayout(LayoutKind.Sequential)] 98[StructLayout(LayoutKind.Sequential)]
60public struct ConvexHull 99public struct ConvexHull
@@ -179,7 +218,20 @@ public struct ConfigurationParameters
179 public const float numericFalse = 0f; 218 public const float numericFalse = 0f;
180} 219}
181 220
182// Values used by Bullet and BulletSim to control collisions 221
222// The states a bullet collision object can have
223public enum ActivationState : uint
224{
225 ACTIVE_TAG = 1,
226 ISLAND_SLEEPING,
227 WANTS_DEACTIVATION,
228 DISABLE_DEACTIVATION,
229 DISABLE_SIMULATION
230}
231
232// Values used by Bullet and BulletSim to control object properties.
233// Bullet's "CollisionFlags" has more to do with operations on the
234// object (if collisions happen, if gravity effects it, ...).
183public enum CollisionFlags : uint 235public enum CollisionFlags : uint
184{ 236{
185 CF_STATIC_OBJECT = 1 << 0, 237 CF_STATIC_OBJECT = 1 << 0,
@@ -194,8 +246,75 @@ public enum CollisionFlags : uint
194 BS_VOLUME_DETECT_OBJECT = 1 << 11, 246 BS_VOLUME_DETECT_OBJECT = 1 << 11,
195 BS_PHANTOM_OBJECT = 1 << 12, 247 BS_PHANTOM_OBJECT = 1 << 12,
196 BS_PHYSICAL_OBJECT = 1 << 13, 248 BS_PHYSICAL_OBJECT = 1 << 13,
249 BS_TERRAIN_OBJECT = 1 << 14,
250 BS_NONE = 0,
251 BS_ALL = 0xFFFFFFFF
197}; 252};
198 253
254// Values for collisions groups and masks
255public enum CollisionFilterGroups : uint
256{
257 NoneFilter = 0,
258 DefaultFilter = 1 << 0,
259 StaticFilter = 1 << 1,
260 KinematicFilter = 1 << 2,
261 DebrisFilter = 1 << 3,
262 SensorTrigger = 1 << 4,
263 CharacterFilter = 1 << 5,
264 AllFilter = 0xFFFFFFFF,
265 // Filter groups defined by BulletSim
266 GroundPlaneFilter = 1 << 10,
267 TerrainFilter = 1 << 11,
268 RaycastFilter = 1 << 12,
269 SolidFilter = 1 << 13,
270};
271
272 // For each type, we first clear and then set the collision flags
273public enum ClearCollisionFlag : uint
274{
275 Terrain = CollisionFlags.BS_ALL,
276 Phantom = CollisionFlags.BS_ALL,
277 VolumeDetect = CollisionFlags.BS_ALL,
278 PhysicalObject = CollisionFlags.BS_ALL,
279 StaticObject = CollisionFlags.BS_ALL
280}
281
282public enum SetCollisionFlag : uint
283{
284 Terrain = CollisionFlags.CF_STATIC_OBJECT
285 | CollisionFlags.BS_TERRAIN_OBJECT,
286 Phantom = CollisionFlags.CF_STATIC_OBJECT
287 | CollisionFlags.BS_PHANTOM_OBJECT
288 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
289 VolumeDetect = CollisionFlags.CF_STATIC_OBJECT
290 | CollisionFlags.BS_VOLUME_DETECT_OBJECT
291 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
292 PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT,
293 StaticObject = CollisionFlags.CF_STATIC_OBJECT,
294}
295
296// Collision filters used for different types of objects
297public enum SetCollisionFilter : uint
298{
299 Terrain = CollisionFilterGroups.AllFilter,
300 Phantom = CollisionFilterGroups.GroundPlaneFilter
301 | CollisionFilterGroups.TerrainFilter,
302 VolumeDetect = CollisionFilterGroups.AllFilter,
303 PhysicalObject = CollisionFilterGroups.AllFilter,
304 StaticObject = CollisionFilterGroups.AllFilter,
305}
306
307// Collision masks used for different types of objects
308public enum SetCollisionMask : uint
309{
310 Terrain = CollisionFilterGroups.AllFilter,
311 Phantom = CollisionFilterGroups.GroundPlaneFilter
312 | CollisionFilterGroups.TerrainFilter,
313 VolumeDetect = CollisionFilterGroups.AllFilter,
314 PhysicalObject = CollisionFilterGroups.AllFilter,
315 StaticObject = CollisionFilterGroups.AllFilter
316}
317
199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 318// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
200// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 319// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
201public enum ConstraintParams : int 320public enum ConstraintParams : int
@@ -221,6 +340,10 @@ public enum ConstraintParamAxis : int
221// =============================================================================== 340// ===============================================================================
222static class BulletSimAPI { 341static class BulletSimAPI {
223 342
343// Link back to the managed code for outputting log messages
344[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
345public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
346
224[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
225[return: MarshalAs(UnmanagedType.LPStr)] 348[return: MarshalAs(UnmanagedType.LPStr)]
226public static extern string GetVersion(); 349public static extern string GetVersion();
@@ -228,7 +351,11 @@ public static extern string GetVersion();
228[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 351[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
229public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, 352public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
230 int maxCollisions, IntPtr collisionArray, 353 int maxCollisions, IntPtr collisionArray,
231 int maxUpdates, IntPtr updateArray); 354 int maxUpdates, IntPtr updateArray,
355 DebugLogCallback logRoutine);
356
357[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
358public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
232 359
233[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 360[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
234public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); 361public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
@@ -300,6 +427,7 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc
300[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 427[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
301public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); 428public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
302 429
430// Set the current force acting on the object
303[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 431[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
304public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); 432public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
305 433
@@ -342,8 +470,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
342public static extern void DumpBulletStatistics(); 470public static extern void DumpBulletStatistics();
343 471
344// Log a debug message 472// Log a debug message
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 473[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
348public static extern void SetDebugLogCallback(DebugLogCallback callback); 474public static extern void SetDebugLogCallback(DebugLogCallback callback);
349 475
@@ -358,6 +484,7 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback);
358// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt 484// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
359// and the old code is removed. 485// and the old code is removed.
360 486
487// Functions use while converting from API1 to API2. Can be removed when totally converted.
361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 488[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
362public static extern IntPtr GetSimHandle2(uint worldID); 489public static extern IntPtr GetSimHandle2(uint worldID);
363 490
@@ -368,6 +495,7 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); 495public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
369 496
370// =============================================================================== 497// ===============================================================================
498// Initialization and simulation
371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
372public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, 500public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
373 int maxCollisions, IntPtr collisionArray, 501 int maxCollisions, IntPtr collisionArray,
@@ -377,7 +505,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); 505public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
378 506
379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
380public static extern void SetHeightmap2(IntPtr world, float[] heightmap); 508public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
381 509
382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
383public static extern void Shutdown2(IntPtr sim); 511public static extern void Shutdown2(IntPtr sim);
@@ -392,23 +520,69 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj); 521public static extern bool PushUpdate2(IntPtr obj);
394 522
395/* 523// =====================================================================================
524// Mesh, hull, shape and body creation helper routines
525[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
526public static extern IntPtr CreateMeshShape2(IntPtr world,
527 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
528 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
529
530[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
531public static extern IntPtr CreateHullShape2(IntPtr world,
532 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
536
537[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
538public static extern IntPtr BuildNativeShape2(IntPtr world,
539 float shapeType, float collisionMargin, Vector3 scale);
540
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
543
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
546
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo);
549
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
552
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
554public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
555
556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
557public static extern void ReleaseBodyInfo2(IntPtr obj);
558
559[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
560public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
561
562// =====================================================================================
563// Terrain creation and helper routines
564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
565public static extern void DumpMapInfo(IntPtr sim, IntPtr manInfo);
566
396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 567[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); 568public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
569 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
398 570
399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 571[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
400public static extern bool BuildHull2(IntPtr world, IntPtr mesh); 572public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
573 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
401 574
402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 575[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); 576public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
404 577
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 578[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); 579public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
407 580
408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 581[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); 582public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
410*/
411 583
584// =====================================================================================
585// Constraint creation and helper routines
412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 586[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 587public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
414 Vector3 frame1loc, Quaternion frame1rot, 588 Vector3 frame1loc, Quaternion frame1rot,
@@ -460,11 +634,108 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 634[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); 635public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
462 636
637// =====================================================================================
638// btCollisionWorld entries
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 639[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); 640public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
465 641
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 642[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 643public static extern void UpdateAabbs2(IntPtr world);
644
645[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
646public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
647
648[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
649public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
650
651// =====================================================================================
652// btDynamicsWorld entries
653[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
654public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
655
656[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
657public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
658
659[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
660public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
661
662[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
663public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
664// =====================================================================================
665// btCollisionObject entries
666[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
667public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
668
669[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
670public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
671
672[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
673public static extern bool HasAnisotripicFriction2(IntPtr constrain);
674
675[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
676public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
677
678[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
679public static extern float GetContactProcessingThreshold2(IntPtr obj);
680
681[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
682public static extern bool IsStaticObject2(IntPtr obj);
683
684[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
685public static extern bool IsKinematicObject2(IntPtr obj);
686
687[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
688public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
689
690[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
691public static extern bool HasContactResponse2(IntPtr obj);
692
693[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
694public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
695
696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
697public static extern IntPtr GetCollisionShape2(IntPtr obj);
698
699[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
700public static extern int GetActivationState2(IntPtr obj);
701
702[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
703public static extern void SetActivationState2(IntPtr obj, int state);
704
705[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
706public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
707
708[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
709public static extern float GetDeactivationTime2(IntPtr obj);
710
711[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
712public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
713
714[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
715public static extern void Activate2(IntPtr obj, bool forceActivation);
716
717[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
718public static extern bool IsActive2(IntPtr obj);
719
720[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
721public static extern void SetRestitution2(IntPtr obj, float val);
722
723[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
724public static extern float GetRestitution2(IntPtr obj);
725
726[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
727public static extern void SetFriction2(IntPtr obj, float val);
728
729[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
730public static extern float GetFriction2(IntPtr obj);
731
732 /* Haven't defined the type 'Transform'
733[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
734public static extern Transform GetWorldTransform2(IntPtr obj);
735
736[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
737public static extern void setWorldTransform2(IntPtr obj, Transform trans);
738 */
468 739
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 740[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern Vector3 GetPosition2(IntPtr obj); 741public static extern Vector3 GetPosition2(IntPtr obj);
@@ -473,86 +744,288 @@ public static extern Vector3 GetPosition2(IntPtr obj);
473public static extern Quaternion GetOrientation2(IntPtr obj); 744public static extern Quaternion GetOrientation2(IntPtr obj);
474 745
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 746[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); 747public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
477 748
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 749[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); 750public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
480 751
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 752[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); 753public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
483 754
755 /*
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 756[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 757public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
486 758
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 759[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); 760public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
761 */
489 762
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 763[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 764public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
492 765
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 766[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); 767public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
495 768
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 769[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); 770public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
498 771
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 772[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern bool SetDeactivationTime2(IntPtr obj, float val); 773public static extern float GetHitFraction2(IntPtr obj);
501 774
502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 775[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
503public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); 776public static extern void SetHitFraction2(IntPtr obj, float val);
504 777
505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 778[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
506public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); 779public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
507 780
508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 781[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
509public static extern bool SetFriction2(IntPtr obj, float val); 782public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
510 783
511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 784[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
512public static extern bool SetRestitution2(IntPtr obj, float val); 785public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
513 786
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 787[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); 788public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
516 789
517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 790[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 791public static extern float GetCcdMotionThreshold2(IntPtr obj);
519 792
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 793[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); 794public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
795
796[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
797public static extern float GetCcdSweepSphereRadius2(IntPtr obj);
798
799[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
800public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val);
801
802[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
803public static extern IntPtr GetUserPointer2(IntPtr obj);
804
805[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
806public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
807
808// =====================================================================================
809// btRigidBody entries
810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
811public static extern void ApplyGravity2(IntPtr obj);
812
813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
814public static extern void SetGravity2(IntPtr obj, Vector3 val);
815
816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
817public static extern Vector3 GetGravity2(IntPtr obj);
818
819[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
820public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
821
822[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
823public static extern float GetLinearDamping2(IntPtr obj);
824
825[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
826public static extern float GetAngularDamping2(IntPtr obj);
827
828[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
829public static extern float GetLinearSleepingThreshold2(IntPtr obj);
830
831[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
832public static extern float GetAngularSleepingThreshold2(IntPtr obj);
833
834[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
835public static extern void ApplyDamping2(IntPtr obj, float timeStep);
836
837[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
838public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
839
840[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
841public static extern Vector3 GetLinearFactor2(IntPtr obj);
842
843[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
844public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
845
846 /*
847[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
848public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
849 */
850
851[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
852public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
853
854// Add a force to the object as if its mass is one.
855[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
856public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
857
858// Set the force being applied to the object as if its mass is one.
859[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
860public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
861
862[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
863public static extern Vector3 GetTotalForce2(IntPtr obj);
864
865[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
866public static extern Vector3 GetTotalTorque2(IntPtr obj);
867
868[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
869public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
870
871[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
872public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
873
874[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
875public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
876
877[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
878public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
879
880// Apply force at the given point. Will add torque to the object.
881[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
882public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
883
884// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
885[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
886public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
887
888// Apply impulse to the object's torque. Force is scaled by object's mass.
889[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
890public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
891
892// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
893[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
894public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
895
896[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
897public static extern void ClearForces2(IntPtr obj);
898
899[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
900public static extern void ClearAllForces2(IntPtr obj);
901
902[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
903public static extern void UpdateInertiaTensor2(IntPtr obj);
904
905[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
906public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
907
908 /*
909[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
910public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
911 */
912
913[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
914public static extern Vector3 GetLinearVelocity2(IntPtr obj);
915
916[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
917public static extern Vector3 GetAngularVelocity2(IntPtr obj);
918
919[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
920public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
921
922[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
923public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
924
925[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
926public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
927
928[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
929public static extern void Translate2(IntPtr obj, Vector3 trans);
930
931[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
932public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
933
934[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
935public static extern bool WantsSleeping2(IntPtr obj);
936
937[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
938public static extern void SetAngularFactor2(IntPtr obj, float factor);
939
940[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
941public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
942
943[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
944public static extern Vector3 GetAngularFactor2(IntPtr obj);
945
946[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
947public static extern bool IsInWorld2(IntPtr obj);
948
949[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
950public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
951
952[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
953public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
954
955[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
956public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
957
958[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
959public static extern int GetNumConstraintRefs2(IntPtr obj);
960
961[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
962public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
963
964[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
965public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
966
967[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
968public static extern Vector3 GetPushVelocity2(IntPtr obj);
969
970[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
971public static extern Vector3 GetTurnVelocity2(IntPtr obj);
972
973// =====================================================================================
974// btCollisionShape entries
975
976[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
977public static extern float GetAngularMotionDisc2(IntPtr shape);
978
979[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
980public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
981
982[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
983public static extern bool IsPolyhedral2(IntPtr shape);
984
985[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
986public static extern bool IsConvex2d2(IntPtr shape);
987
988[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
989public static extern bool IsConvex2(IntPtr shape);
990
991[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
992public static extern bool IsNonMoving2(IntPtr shape);
522 993
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 994[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); 995public static extern bool IsConcave2(IntPtr shape);
525 996
526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 997[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); 998public static extern bool IsCompound2(IntPtr shape);
528 999
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1000[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); 1001public static extern bool IsSoftBody2(IntPtr shape);
531 1002
532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1003[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 1004public static extern bool IsInfinite2(IntPtr shape);
534 1005
535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1006[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
536public static extern bool UpdateInertiaTensor2(IntPtr obj); 1007public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
537 1008
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1009[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern bool SetGravity2(IntPtr obj, Vector3 val); 1010public static extern Vector3 GetLocalScaling2(IntPtr shape);
540 1011
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern IntPtr ClearForces2(IntPtr obj); 1013public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia);
543 1014
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr ClearAllForces2(IntPtr obj); 1016public static extern int GetShapeType2(IntPtr shape);
546 1017
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1018[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern bool SetMargin2(IntPtr obj, float val); 1019public static extern void SetMargin2(IntPtr shape, float val);
549 1020
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1021[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 1022public static extern float GetMargin2(IntPtr shape);
552 1023
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1024[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
554public static extern bool DestroyObject2(IntPtr world, uint id); 1025public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask);
555 1026
1027// =====================================================================================
1028// Debugging
556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1029[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
557public static extern void DumpPhysicsStatistics2(IntPtr sim); 1030public static extern void DumpPhysicsStatistics2(IntPtr sim);
558 1031
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 3144d76..190fca0 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -39,11 +39,8 @@ using OpenSim.Framework.Console;
39using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
40using Mono.Addins; 40using Mono.Addins;
41 41
42[assembly: Addin("RegionCombinerModule", "0.1")]
43[assembly: AddinDependency("OpenSim", "0.5")]
44namespace OpenSim.Region.RegionCombinerModule 42namespace OpenSim.Region.RegionCombinerModule
45{ 43{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
47 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule 44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
48 { 45 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
new file mode 100644
index 0000000..13cb8b6
--- /dev/null
+++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
@@ -0,0 +1,14 @@
1<Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3">
2 <Runtime>
3 <Import assembly="OpenSim.Region.RegionCombinerModule.dll"/>
4 </Runtime>
5
6 <Dependencies>
7 <Addin id="OpenSim" version="0.5" />
8 </Dependencies>
9
10 <Extension path = "/OpenSim/RegionModules">
11 <RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" />
12 </Extension>
13
14</Addin>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index f9b4bfd..9570669 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -341,7 +341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
341 return GetLinkParts(m_host, linkType); 341 return GetLinkParts(m_host, linkType);
342 } 342 }
343 343
344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 344 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
345 { 345 {
346 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 346 List<SceneObjectPart> ret = new List<SceneObjectPart>();
347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -426,14 +426,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
426 return key; 426 return key;
427 } 427 }
428 428
429 // convert a LSL_Rotation to a Quaternion
430 public static Quaternion Rot2Quaternion(LSL_Rotation r)
431 {
432 Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
433 q.Normalize();
434 return q;
435 }
436
437 //These are the implementations of the various ll-functions used by the LSL scripts. 429 //These are the implementations of the various ll-functions used by the LSL scripts.
438 public LSL_Float llSin(double f) 430 public LSL_Float llSin(double f)
439 { 431 {
@@ -1240,9 +1232,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1240 public LSL_Float llGround(LSL_Vector offset) 1232 public LSL_Float llGround(LSL_Vector offset)
1241 { 1233 {
1242 m_host.AddScriptLPS(1); 1234 m_host.AddScriptLPS(1);
1243 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 1235 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
1244 (float)offset.y,
1245 (float)offset.z);
1246 1236
1247 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 1237 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1248 LSL_Vector vsn = llGroundNormal(offset); 1238 LSL_Vector vsn = llGroundNormal(offset);
@@ -1492,31 +1482,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 if (part == null || part.ParentGroup.IsDeleted) 1482 if (part == null || part.ParentGroup.IsDeleted)
1493 return; 1483 return;
1494 1484
1495 if (scale.x < 0.01) 1485 // First we need to check whether or not we need to clamp the size of a physics-enabled prim
1496 scale.x = 0.01;
1497 if (scale.y < 0.01)
1498 scale.y = 0.01;
1499 if (scale.z < 0.01)
1500 scale.z = 0.01;
1501
1502 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; 1486 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1503
1504 if (pa != null && pa.IsPhysical) 1487 if (pa != null && pa.IsPhysical)
1505 { 1488 {
1506 if (scale.x > World.m_maxPhys) 1489 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
1507 scale.x = World.m_maxPhys; 1490 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
1508 if (scale.y > World.m_maxPhys) 1491 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
1509 scale.y = World.m_maxPhys; 1492 }
1510 if (scale.z > World.m_maxPhys) 1493 else
1511 scale.z = World.m_maxPhys; 1494 {
1495 // If not physical, then we clamp the scale to the non-physical min/max
1496 scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
1497 scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
1498 scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
1512 } 1499 }
1513
1514 if (scale.x > World.m_maxNonphys)
1515 scale.x = World.m_maxNonphys;
1516 if (scale.y > World.m_maxNonphys)
1517 scale.y = World.m_maxNonphys;
1518 if (scale.z > World.m_maxNonphys)
1519 scale.z = World.m_maxNonphys;
1520 1500
1521 Vector3 tmp = part.Scale; 1501 Vector3 tmp = part.Scale;
1522 tmp.X = (float)scale.x; 1502 tmp.X = (float)scale.x;
@@ -1590,7 +1570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1590 if (face == ScriptBaseClass.ALL_SIDES) 1570 if (face == ScriptBaseClass.ALL_SIDES)
1591 face = SceneObjectPart.ALL_SIDES; 1571 face = SceneObjectPart.ALL_SIDES;
1592 1572
1593 m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 1573 m_host.SetFaceColorAlpha(face, color, null);
1594 } 1574 }
1595 1575
1596 public void SetTexGen(SceneObjectPart part, int face,int style) 1576 public void SetTexGen(SceneObjectPart part, int face,int style)
@@ -2202,7 +2182,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2202 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2182 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2203 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2183 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2204 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2184 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2205 pos.z > 4096 // return FALSE if altitude than 4096m 2185 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2206 ) 2186 )
2207 ) 2187 )
2208 { 2188 {
@@ -2213,14 +2193,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2213 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. 2193 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2214 2194
2215 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; 2195 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2216 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); 2196 LandData here = World.GetLandData(objectPos);
2217 LandData there = World.GetLandData((float)pos.x, (float)pos.y); 2197 LandData there = World.GetLandData(pos);
2218 2198
2219 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. 2199 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2220 2200
2221 bool sameParcel = here.GlobalID == there.GlobalID; 2201 bool sameParcel = here.GlobalID == there.GlobalID;
2222 2202
2223 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) 2203 if (!sameParcel && !World.Permissions.CanRezObject(
2204 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2224 { 2205 {
2225 return 0; 2206 return 0;
2226 } 2207 }
@@ -2279,16 +2260,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2279 if (part.ParentGroup.RootPart == part) 2260 if (part.ParentGroup.RootPart == part)
2280 { 2261 {
2281 SceneObjectGroup parent = part.ParentGroup; 2262 SceneObjectGroup parent = part.ParentGroup;
2282 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2263 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2283 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2284 return; 2264 return;
2285 Util.FireAndForget(delegate(object x) { 2265 Util.FireAndForget(delegate(object x) {
2286 parent.UpdateGroupPosition(dest); 2266 parent.UpdateGroupPosition((Vector3)toPos);
2287 }); 2267 });
2288 } 2268 }
2289 else 2269 else
2290 { 2270 {
2291 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2271 part.OffsetPosition = (Vector3)toPos;
2292 SceneObjectGroup parent = part.ParentGroup; 2272 SceneObjectGroup parent = part.ParentGroup;
2293 parent.HasGroupChanged = true; 2273 parent.HasGroupChanged = true;
2294 parent.ScheduleGroupForTerseUpdate(); 2274 parent.ScheduleGroupForTerseUpdate();
@@ -2326,7 +2306,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2326 pos = part.AbsolutePosition; 2306 pos = part.AbsolutePosition;
2327 } 2307 }
2328 2308
2329 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2309// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2310
2311 return new LSL_Vector(pos);
2330 } 2312 }
2331 2313
2332 public void llSetRot(LSL_Rotation rot) 2314 public void llSetRot(LSL_Rotation rot)
@@ -2334,26 +2316,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2334 m_host.AddScriptLPS(1); 2316 m_host.AddScriptLPS(1);
2335 2317
2336 // try to let this work as in SL... 2318 // try to let this work as in SL...
2337 if (m_host.LinkNum < 2) 2319 if (m_host.ParentID == 0)
2338 { 2320 {
2339 // Special case: If we are root, rotate complete SOG to new 2321 // special case: If we are root, rotate complete SOG to new rotation
2340 // rotation. 2322 SetRot(m_host, rot);
2341 // We are root if the link number is 0 (single prim) or 1
2342 // (root prim). ParentID may be nonzero in attachments and
2343 // using it would cause attachments and HUDs to rotate
2344 // to the wrong positions.
2345
2346 SetRot(m_host, Rot2Quaternion(rot));
2347 } 2323 }
2348 else 2324 else
2349 { 2325 {
2350 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 2326 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2351 SceneObjectPart rootPart; 2327 SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
2352 if (m_host.ParentGroup != null) // better safe than sorry 2328 if (rootPart != null) // better safe than sorry
2353 { 2329 {
2354 rootPart = m_host.ParentGroup.RootPart; 2330 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2355 if (rootPart != null)
2356 SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot));
2357 } 2331 }
2358 } 2332 }
2359 2333
@@ -2363,8 +2337,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2363 public void llSetLocalRot(LSL_Rotation rot) 2337 public void llSetLocalRot(LSL_Rotation rot)
2364 { 2338 {
2365 m_host.AddScriptLPS(1); 2339 m_host.AddScriptLPS(1);
2366 2340 SetRot(m_host, rot);
2367 SetRot(m_host, Rot2Quaternion(rot));
2368 ScriptSleep(200); 2341 ScriptSleep(200);
2369 } 2342 }
2370 2343
@@ -2476,7 +2449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2476 if (local != 0) 2449 if (local != 0)
2477 force *= llGetRot(); 2450 force *= llGetRot();
2478 2451
2479 m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); 2452 m_host.ParentGroup.RootPart.SetForce(force);
2480 } 2453 }
2481 } 2454 }
2482 2455
@@ -2488,10 +2461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2488 2461
2489 if (!m_host.ParentGroup.IsDeleted) 2462 if (!m_host.ParentGroup.IsDeleted)
2490 { 2463 {
2491 Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); 2464 force = m_host.ParentGroup.RootPart.GetForce();
2492 force.x = tmpForce.X;
2493 force.y = tmpForce.Y;
2494 force.z = tmpForce.Z;
2495 } 2465 }
2496 2466
2497 return force; 2467 return force;
@@ -2500,8 +2470,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 public LSL_Integer llTarget(LSL_Vector position, double range) 2470 public LSL_Integer llTarget(LSL_Vector position, double range)
2501 { 2471 {
2502 m_host.AddScriptLPS(1); 2472 m_host.AddScriptLPS(1);
2503 return m_host.ParentGroup.registerTargetWaypoint( 2473 return m_host.ParentGroup.registerTargetWaypoint(position,
2504 new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); 2474 (float)range);
2505 } 2475 }
2506 2476
2507 public void llTargetRemove(int number) 2477 public void llTargetRemove(int number)
@@ -2513,8 +2483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2513 public LSL_Integer llRotTarget(LSL_Rotation rot, double error) 2483 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2514 { 2484 {
2515 m_host.AddScriptLPS(1); 2485 m_host.AddScriptLPS(1);
2516 return m_host.ParentGroup.registerRotTargetWaypoint( 2486 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
2517 new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
2518 } 2487 }
2519 2488
2520 public void llRotTargetRemove(int number) 2489 public void llRotTargetRemove(int number)
@@ -2526,7 +2495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2526 public void llMoveToTarget(LSL_Vector target, double tau) 2495 public void llMoveToTarget(LSL_Vector target, double tau)
2527 { 2496 {
2528 m_host.AddScriptLPS(1); 2497 m_host.AddScriptLPS(1);
2529 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); 2498 m_host.MoveToTarget(target, (float)tau);
2530 } 2499 }
2531 2500
2532 public void llStopMoveToTarget() 2501 public void llStopMoveToTarget()
@@ -2539,7 +2508,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2539 { 2508 {
2540 m_host.AddScriptLPS(1); 2509 m_host.AddScriptLPS(1);
2541 //No energy force yet 2510 //No energy force yet
2542 Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); 2511 Vector3 v = force;
2543 if (v.Length() > 20000.0f) 2512 if (v.Length() > 20000.0f)
2544 { 2513 {
2545 v.Normalize(); 2514 v.Normalize();
@@ -2552,13 +2521,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2552 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2521 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2553 { 2522 {
2554 m_host.AddScriptLPS(1); 2523 m_host.AddScriptLPS(1);
2555 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2524 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2556 } 2525 }
2557 2526
2558 public void llSetTorque(LSL_Vector torque, int local) 2527 public void llSetTorque(LSL_Vector torque, int local)
2559 { 2528 {
2560 m_host.AddScriptLPS(1); 2529 m_host.AddScriptLPS(1);
2561 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2530 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2562 } 2531 }
2563 2532
2564 public LSL_Vector llGetTorque() 2533 public LSL_Vector llGetTorque()
@@ -3123,13 +3092,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3123 return; 3092 return;
3124 } 3093 }
3125 3094
3126 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
3127 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
3128
3129 // need the magnitude later 3095 // need the magnitude later
3130 // float velmag = (float)Util.GetMagnitude(llvel); 3096 // float velmag = (float)Util.GetMagnitude(llvel);
3131 3097
3132 SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); 3098 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param);
3133 3099
3134 // If either of these are null, then there was an unknown error. 3100 // If either of these are null, then there was an unknown error.
3135 if (new_group == null) 3101 if (new_group == null)
@@ -3156,11 +3122,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3156 3122
3157 PhysicsActor pa = new_group.RootPart.PhysActor; 3123 PhysicsActor pa = new_group.RootPart.PhysActor;
3158 3124
3159 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3125 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3160 { 3126 {
3161 float groupmass = new_group.GetMass(); 3127 float groupmass = new_group.GetMass();
3162 llvel *= -groupmass; 3128 vel *= -groupmass;
3163 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); 3129 llApplyImpulse(vel, 0);
3164 } 3130 }
3165 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3131 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3166 return; 3132 return;
@@ -3211,7 +3177,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3211 return; 3177 return;
3212 } 3178 }
3213 3179
3214 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); 3180 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
3215 } 3181 }
3216 } 3182 }
3217 3183
@@ -3637,7 +3603,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3637 } 3603 }
3638 else 3604 else
3639 { 3605 {
3640 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); 3606 m_host.RotLookAt(target, (float)strength, (float)damping);
3641 } 3607 }
3642 } 3608 }
3643 3609
@@ -3718,7 +3684,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3718 3684
3719 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3685 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3720 { 3686 {
3721 part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); 3687 part.UpdateAngularVelocity(axis * spinrate);
3722 } 3688 }
3723 3689
3724 public LSL_Integer llGetStartParameter() 3690 public LSL_Integer llGetStartParameter()
@@ -3928,7 +3894,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3928 try 3894 try
3929 { 3895 {
3930 foreach (SceneObjectPart part in parts) 3896 foreach (SceneObjectPart part in parts)
3931 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3897 part.SetFaceColorAlpha(face, color, null);
3932 } 3898 }
3933 finally 3899 finally
3934 { 3900 {
@@ -4398,9 +4364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4398 public void llSetText(string text, LSL_Vector color, double alpha) 4364 public void llSetText(string text, LSL_Vector color, double alpha)
4399 { 4365 {
4400 m_host.AddScriptLPS(1); 4366 m_host.AddScriptLPS(1);
4401 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), 4367 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4402 Util.Clip((float)color.y, 0.0f, 1.0f),
4403 Util.Clip((float)color.z, 0.0f, 1.0f));
4404 m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); 4368 m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
4405 //m_host.ParentGroup.HasGroupChanged = true; 4369 //m_host.ParentGroup.HasGroupChanged = true;
4406 //m_host.ParentGroup.ScheduleGroupForFullUpdate(); 4370 //m_host.ParentGroup.ScheduleGroupForFullUpdate();
@@ -4616,14 +4580,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4616 ScriptSleep(5000); 4580 ScriptSleep(5000);
4617 } 4581 }
4618 4582
4619 public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) 4583 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
4620 { 4584 {
4621 m_host.AddScriptLPS(1); 4585 m_host.AddScriptLPS(1);
4622 UUID agentId = new UUID(); 4586 UUID agentId = new UUID();
4623 4587
4624 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4625 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4626
4627 if (UUID.TryParse(agent, out agentId)) 4588 if (UUID.TryParse(agent, out agentId))
4628 { 4589 {
4629 ScenePresence presence = World.GetScenePresence(agentId); 4590 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4652,15 +4613,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4652 } 4613 }
4653 } 4614 }
4654 4615
4655 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) 4616 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
4656 { 4617 {
4657 m_host.AddScriptLPS(1); 4618 m_host.AddScriptLPS(1);
4658 UUID agentId = new UUID(); 4619 UUID agentId = new UUID();
4659 4620
4660 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4621 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y);
4661 4622
4662 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4663 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4664 if (UUID.TryParse(agent, out agentId)) 4623 if (UUID.TryParse(agent, out agentId))
4665 { 4624 {
4666 ScenePresence presence = World.GetScenePresence(agentId); 4625 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4957,7 +4916,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4957 distance_attenuation = 1f / normalized_units; 4916 distance_attenuation = 1f / normalized_units;
4958 } 4917 }
4959 4918
4960 Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); 4919 Vector3 applied_linear_impulse = impulse;
4961 { 4920 {
4962 float impulse_length = applied_linear_impulse.Length(); 4921 float impulse_length = applied_linear_impulse.Length();
4963 4922
@@ -5605,25 +5564,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5605 /// separated list. There is a space after 5564 /// separated list. There is a space after
5606 /// each comma. 5565 /// each comma.
5607 /// </summary> 5566 /// </summary>
5608
5609 public LSL_String llList2CSV(LSL_List src) 5567 public LSL_String llList2CSV(LSL_List src)
5610 { 5568 {
5611
5612 string ret = String.Empty;
5613 int x = 0;
5614
5615 m_host.AddScriptLPS(1); 5569 m_host.AddScriptLPS(1);
5616 5570
5617 if (src.Data.Length > 0) 5571 return string.Join(", ",
5618 { 5572 (new List<object>(src.Data)).ConvertAll<string>(o =>
5619 ret = src.Data[x++].ToString(); 5573 {
5620 for (; x < src.Data.Length; x++) 5574 return o.ToString();
5621 { 5575 }).ToArray());
5622 ret += ", "+src.Data[x].ToString();
5623 }
5624 }
5625
5626 return ret;
5627 } 5576 }
5628 5577
5629 /// <summary> 5578 /// <summary>
@@ -6296,19 +6245,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6296 m_host.AddScriptLPS(1); 6245 m_host.AddScriptLPS(1);
6297 6246
6298 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6247 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6299 if (parts.Count > 0) 6248
6249 try
6300 { 6250 {
6301 try 6251 foreach (SceneObjectPart part in parts)
6302 {
6303 foreach (var part in parts)
6304 {
6305 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6306 }
6307 }
6308 finally
6309 { 6252 {
6253 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6310 } 6254 }
6311 } 6255 }
6256 finally
6257 {
6258 }
6312 } 6259 }
6313 6260
6314 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6261 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
@@ -6526,9 +6473,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6526 6473
6527 //Plug the x,y coordinates of the slope normal into the equation of the plane to get 6474 //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6528 //the height of that point on the plane. The resulting vector gives the slope. 6475 //the height of that point on the plane. The resulting vector gives the slope.
6529 Vector3 vsl = new Vector3(); 6476 Vector3 vsl = vsn;
6530 vsl.X = (float)vsn.x;
6531 vsl.Y = (float)vsn.y;
6532 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); 6477 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6533 vsl.Normalize(); 6478 vsl.Normalize();
6534 //Normalization might be overkill here 6479 //Normalization might be overkill here
@@ -6539,9 +6484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6539 public LSL_Vector llGroundNormal(LSL_Vector offset) 6484 public LSL_Vector llGroundNormal(LSL_Vector offset)
6540 { 6485 {
6541 m_host.AddScriptLPS(1); 6486 m_host.AddScriptLPS(1);
6542 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 6487 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
6543 (float)offset.y,
6544 (float)offset.z);
6545 // Clamp to valid position 6488 // Clamp to valid position
6546 if (pos.X < 0) 6489 if (pos.X < 0)
6547 pos.X = 0; 6490 pos.X = 0;
@@ -6706,7 +6649,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6706 6649
6707 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6650 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6708 6651
6709 foreach (var part in parts) 6652 foreach (SceneObjectPart part in parts)
6710 { 6653 {
6711 SetParticleSystem(part, rules); 6654 SetParticleSystem(part, rules);
6712 } 6655 }
@@ -6995,8 +6938,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6995 6938
6996 if (!m_host.ParentGroup.IsDeleted) 6939 if (!m_host.ParentGroup.IsDeleted)
6997 { 6940 {
6998 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, 6941 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
6999 new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
7000 } 6942 }
7001 } 6943 }
7002 6944
@@ -7008,7 +6950,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7008 6950
7009 if (!m_host.ParentGroup.IsDeleted) 6951 if (!m_host.ParentGroup.IsDeleted)
7010 { 6952 {
7011 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); 6953 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot);
7012 } 6954 }
7013 } 6955 }
7014 6956
@@ -7038,8 +6980,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7038 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 6980 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7039 rot.s = 1; // ZERO_ROTATION = 0,0,0,1 6981 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7040 6982
7041 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); 6983 part.SitTargetPosition = offset;
7042 part.SitTargetOrientation = Rot2Quaternion(rot); 6984 part.SitTargetOrientation = rot;
7043 part.ParentGroup.HasGroupChanged = true; 6985 part.ParentGroup.HasGroupChanged = true;
7044 } 6986 }
7045 6987
@@ -7142,13 +7084,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7142 public void llSetCameraEyeOffset(LSL_Vector offset) 7084 public void llSetCameraEyeOffset(LSL_Vector offset)
7143 { 7085 {
7144 m_host.AddScriptLPS(1); 7086 m_host.AddScriptLPS(1);
7145 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7087 m_host.SetCameraEyeOffset(offset);
7146 } 7088 }
7147 7089
7148 public void llSetCameraAtOffset(LSL_Vector offset) 7090 public void llSetCameraAtOffset(LSL_Vector offset)
7149 { 7091 {
7150 m_host.AddScriptLPS(1); 7092 m_host.AddScriptLPS(1);
7151 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7093 m_host.SetCameraAtOffset(offset);
7152 } 7094 }
7153 7095
7154 public LSL_String llDumpList2String(LSL_List src, string seperator) 7096 public LSL_String llDumpList2String(LSL_List src, string seperator)
@@ -7170,7 +7112,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7170 public LSL_Integer llScriptDanger(LSL_Vector pos) 7112 public LSL_Integer llScriptDanger(LSL_Vector pos)
7171 { 7113 {
7172 m_host.AddScriptLPS(1); 7114 m_host.AddScriptLPS(1);
7173 bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); 7115 bool result = World.ScriptDanger(m_host.LocalId, pos);
7174 if (result) 7116 if (result)
7175 { 7117 {
7176 return 1; 7118 return 1;
@@ -7752,7 +7694,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7752 { 7694 {
7753 m_host.AddScriptLPS(1); 7695 m_host.AddScriptLPS(1);
7754 7696
7755 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); 7697 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
7756 7698
7757 ScriptSleep(200); 7699 ScriptSleep(200);
7758 } 7700 }
@@ -7761,10 +7703,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7761 { 7703 {
7762 m_host.AddScriptLPS(1); 7704 m_host.AddScriptLPS(1);
7763 7705
7764 setLinkPrimParams(linknumber, rules); 7706 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7707
7708 ScriptSleep(200);
7765 } 7709 }
7766 7710
7767 private void setLinkPrimParams(int linknumber, LSL_List rules) 7711 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7768 { 7712 {
7769 List<object> parts = new List<object>(); 7713 List<object> parts = new List<object>();
7770 List<SceneObjectPart> prims = GetLinkParts(linknumber); 7714 List<SceneObjectPart> prims = GetLinkParts(linknumber);
@@ -7775,15 +7719,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7775 parts.Add(p); 7719 parts.Add(p);
7776 7720
7777 LSL_List remaining = null; 7721 LSL_List remaining = null;
7722 uint rulesParsed = 0;
7778 7723
7779 if (parts.Count > 0) 7724 if (parts.Count > 0)
7780 { 7725 {
7781 foreach (object part in parts) 7726 foreach (object part in parts)
7782 { 7727 {
7783 if (part is SceneObjectPart) 7728 if (part is SceneObjectPart)
7784 remaining = SetPrimParams((SceneObjectPart)part, rules); 7729 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7785 else 7730 else
7786 remaining = SetPrimParams((ScenePresence)part, rules); 7731 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7787 } 7732 }
7788 7733
7789 while ((object)remaining != null && remaining.Length > 2) 7734 while ((object)remaining != null && remaining.Length > 2)
@@ -7802,9 +7747,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7802 foreach (object part in parts) 7747 foreach (object part in parts)
7803 { 7748 {
7804 if (part is SceneObjectPart) 7749 if (part is SceneObjectPart)
7805 remaining = SetPrimParams((SceneObjectPart)part, rules); 7750 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7806 else 7751 else
7807 remaining = SetPrimParams((ScenePresence)part, rules); 7752 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7808 } 7753 }
7809 } 7754 }
7810 } 7755 }
@@ -7842,6 +7787,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7842 7787
7843 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7788 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7844 { 7789 {
7790 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7845 llSetLinkPrimitiveParamsFast(linknumber, rules); 7791 llSetLinkPrimitiveParamsFast(linknumber, rules);
7846 ScriptSleep(200); 7792 ScriptSleep(200);
7847 } 7793 }
@@ -7869,195 +7815,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7869 return new Vector3((float)x, (float)y, (float)z); 7815 return new Vector3((float)x, (float)y, (float)z);
7870 } 7816 }
7871 7817
7872 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) 7818 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7873 {
7874 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7875
7876 int idx = 0;
7877
7878 bool positionChanged = false;
7879 Vector3 finalPos = Vector3.Zero;
7880
7881 try
7882 {
7883 while (idx < rules.Length)
7884 {
7885 int code = rules.GetLSLIntegerItem(idx++);
7886
7887 int remain = rules.Length - idx;
7888
7889 switch (code)
7890 {
7891 case (int)ScriptBaseClass.PRIM_POSITION:
7892 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7893 {
7894 if (remain < 1)
7895 return null;
7896
7897 LSL_Vector v;
7898 v = rules.GetVector3Item(idx++);
7899
7900 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7901 if (part == null)
7902 break;
7903
7904 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7905 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7906 if (part.LinkNum > 1)
7907 {
7908 localRot = GetPartLocalRot(part);
7909 localPos = GetPartLocalPos(part);
7910 }
7911
7912 v -= localPos;
7913 v /= localRot;
7914
7915 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7916
7917 v = v + 2 * sitOffset;
7918
7919 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7920 av.SendAvatarDataToAllAgents();
7921
7922 }
7923 break;
7924
7925 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
7926 case (int)ScriptBaseClass.PRIM_ROTATION:
7927 {
7928 if (remain < 1)
7929 return null;
7930
7931 LSL_Rotation r;
7932 r = rules.GetQuaternionItem(idx++);
7933
7934 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7935 if (part == null)
7936 break;
7937
7938 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7939 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7940
7941 if (part.LinkNum > 1)
7942 localRot = GetPartLocalRot(part);
7943
7944 r = r * llGetRootRotation() / localRot;
7945 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7946 av.SendAvatarDataToAllAgents();
7947 }
7948 break;
7949
7950 // parse rest doing nothing but number of parameters error check
7951 case (int)ScriptBaseClass.PRIM_SIZE:
7952 case (int)ScriptBaseClass.PRIM_MATERIAL:
7953 case (int)ScriptBaseClass.PRIM_PHANTOM:
7954 case (int)ScriptBaseClass.PRIM_PHYSICS:
7955 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7956 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7957 case (int)ScriptBaseClass.PRIM_NAME:
7958 case (int)ScriptBaseClass.PRIM_DESC:
7959 if (remain < 1)
7960 return null;
7961 idx++;
7962 break;
7963
7964 case (int)ScriptBaseClass.PRIM_GLOW:
7965 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7966 case (int)ScriptBaseClass.PRIM_TEXGEN:
7967 if (remain < 2)
7968 return null;
7969 idx += 2;
7970 break;
7971
7972 case (int)ScriptBaseClass.PRIM_TYPE:
7973 if (remain < 3)
7974 return null;
7975 code = (int)rules.GetLSLIntegerItem(idx++);
7976 remain = rules.Length - idx;
7977 switch (code)
7978 {
7979 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
7980 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7981 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7982 if (remain < 6)
7983 return null;
7984 idx += 6;
7985 break;
7986
7987 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
7988 if (remain < 5)
7989 return null;
7990 idx += 5;
7991 break;
7992
7993 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
7994 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
7995 case (int)ScriptBaseClass.PRIM_TYPE_RING:
7996 if (remain < 11)
7997 return null;
7998 idx += 11;
7999 break;
8000
8001 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
8002 if (remain < 2)
8003 return null;
8004 idx += 2;
8005 break;
8006 }
8007 break;
8008
8009 case (int)ScriptBaseClass.PRIM_COLOR:
8010 case (int)ScriptBaseClass.PRIM_TEXT:
8011 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8012 case (int)ScriptBaseClass.PRIM_OMEGA:
8013 if (remain < 3)
8014 return null;
8015 idx += 3;
8016 break;
8017
8018 case (int)ScriptBaseClass.PRIM_TEXTURE:
8019 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8020 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8021 if (remain < 5)
8022 return null;
8023 idx += 5;
8024 break;
8025
8026 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8027 if (remain < 7)
8028 return null;
8029
8030 idx += 7;
8031 break;
8032
8033 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8034 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8035 return null;
8036
8037 return rules.GetSublist(idx, -1);
8038 }
8039 }
8040 }
8041
8042 finally
8043 {
8044 if (positionChanged)
8045 {
8046 av.OffsetPosition = finalPos;
8047// av.SendAvatarDataToAllAgents();
8048 av.SendTerseUpdateToAllClients();
8049 positionChanged = false;
8050 }
8051 }
8052 return null;
8053 }
8054
8055 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
8056 { 7819 {
8057 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7820 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8058 return null; 7821 return null;
8059 7822
8060 int idx = 0; 7823 int idx = 0;
7824 int idxStart = 0;
8061 7825
8062 SceneObjectGroup parentgrp = part.ParentGroup; 7826 SceneObjectGroup parentgrp = part.ParentGroup;
8063 7827
@@ -8068,9 +7832,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8068 { 7832 {
8069 while (idx < rules.Length) 7833 while (idx < rules.Length)
8070 { 7834 {
7835 ++rulesParsed;
8071 int code = rules.GetLSLIntegerItem(idx++); 7836 int code = rules.GetLSLIntegerItem(idx++);
8072 7837
8073 int remain = rules.Length - idx; 7838 int remain = rules.Length - idx;
7839 idxStart = idx;
8074 7840
8075 int face; 7841 int face;
8076 LSL_Vector v; 7842 LSL_Vector v;
@@ -8100,18 +7866,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8100 return null; 7866 return null;
8101 7867
8102 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7868 LSL_Rotation q = rules.GetQuaternionItem(idx++);
8103 SceneObjectPart rootPart = parentgrp.RootPart;
8104 // try to let this work as in SL... 7869 // try to let this work as in SL...
8105 if (rootPart == part) 7870 if (part.ParentID == 0)
8106 { 7871 {
8107 // special case: If we are root, rotate complete SOG to new rotation 7872 // special case: If we are root, rotate complete SOG to new rotation
8108 SetRot(part, Rot2Quaternion(q)); 7873 SetRot(part, q);
8109 } 7874 }
8110 else 7875 else
8111 { 7876 {
8112 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 7877 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
8113 // sounds like sl bug that we need to replicate 7878 SceneObjectPart rootPart = part.ParentGroup.RootPart;
8114 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); 7879 SetRot(part, rootPart.RotationOffset * (Quaternion)q);
8115 } 7880 }
8116 7881
8117 break; 7882 break;
@@ -8285,8 +8050,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8285 LSL_Vector color=rules.GetVector3Item(idx++); 8050 LSL_Vector color=rules.GetVector3Item(idx++);
8286 double alpha=(double)rules.GetLSLFloatItem(idx++); 8051 double alpha=(double)rules.GetLSLFloatItem(idx++);
8287 8052
8288 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 8053 part.SetFaceColorAlpha(face, color, alpha);
8289 SetAlpha(part, alpha, face);
8290 8054
8291 break; 8055 break;
8292 8056
@@ -8434,9 +8198,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8434 string primText = rules.GetLSLStringItem(idx++); 8198 string primText = rules.GetLSLStringItem(idx++);
8435 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 8199 LSL_Vector primTextColor = rules.GetVector3Item(idx++);
8436 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 8200 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
8437 Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), 8201 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
8438 Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
8439 Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
8440 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 8202 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
8441 8203
8442 break; 8204 break;
@@ -8455,8 +8217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8455 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 8217 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8456 if (remain < 1) 8218 if (remain < 1)
8457 return null; 8219 return null;
8458 LSL_Rotation lr = rules.GetQuaternionItem(idx++); 8220 SetRot(part, rules.GetQuaternionItem(idx++));
8459 SetRot(part, Rot2Quaternion(lr));
8460 break; 8221 break;
8461 case (int)ScriptBaseClass.PRIM_OMEGA: 8222 case (int)ScriptBaseClass.PRIM_OMEGA:
8462 if (remain < 3) 8223 if (remain < 3)
@@ -8466,7 +8227,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8466 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8227 LSL_Float gain = rules.GetLSLFloatItem(idx++);
8467 TargetOmega(part, axis, (double)spinrate, (double)gain); 8228 TargetOmega(part, axis, (double)spinrate, (double)gain);
8468 break; 8229 break;
8469 8230 case (int)ScriptBaseClass.PRIM_SLICE:
8231 if (remain < 1)
8232 return null;
8233 LSL_Vector slice = rules.GetVector3Item(idx++);
8234 part.UpdateSlice((float)slice.x, (float)slice.y);
8235 break;
8470 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8236 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8471 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8237 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8472 return null; 8238 return null;
@@ -8475,6 +8241,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8475 } 8241 }
8476 } 8242 }
8477 } 8243 }
8244 catch (InvalidCastException e)
8245 {
8246 ShoutError(string.Format(
8247 "{0} error running rule #{1}: arg #{2} ",
8248 originFunc, rulesParsed, idx - idxStart) + e.Message);
8249 }
8478 finally 8250 finally
8479 { 8251 {
8480 if (positionChanged) 8252 if (positionChanged)
@@ -8483,12 +8255,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8483 { 8255 {
8484 SceneObjectGroup parent = part.ParentGroup; 8256 SceneObjectGroup parent = part.ParentGroup;
8485 Util.FireAndForget(delegate(object x) { 8257 Util.FireAndForget(delegate(object x) {
8486 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8258 parent.UpdateGroupPosition(currentPosition);
8487 }); 8259 });
8488 } 8260 }
8489 else 8261 else
8490 { 8262 {
8491 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); 8263 part.OffsetPosition = currentPosition;
8492 SceneObjectGroup parent = part.ParentGroup; 8264 SceneObjectGroup parent = part.ParentGroup;
8493 parent.HasGroupChanged = true; 8265 parent.HasGroupChanged = true;
8494 parent.ScheduleGroupForTerseUpdate(); 8266 parent.ScheduleGroupForTerseUpdate();
@@ -8866,7 +8638,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8866 public LSL_List llGetPrimitiveParams(LSL_List rules) 8638 public LSL_List llGetPrimitiveParams(LSL_List rules)
8867 { 8639 {
8868 m_host.AddScriptLPS(1); 8640 m_host.AddScriptLPS(1);
8869 return GetLinkPrimitiveParams(m_host, rules); 8641
8642 LSL_List result = new LSL_List();
8643
8644 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
8645
8646 while (remaining != null && remaining.Length > 2)
8647 {
8648 int linknumber = remaining.GetLSLIntegerItem(0);
8649 rules = remaining.GetSublist(1, -1);
8650 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8651
8652 foreach (SceneObjectPart part in parts)
8653 remaining = GetPrimParams(part, rules, ref result);
8654 }
8655
8656 return result;
8870 } 8657 }
8871 8658
8872 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 8659 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -8876,294 +8663,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8876 // acording to SL wiki this must indicate a single link number or link_root or link_this. 8663 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8877 // keep other options as before 8664 // keep other options as before
8878 8665
8879 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8666 List<SceneObjectPart> parts;
8880 List<ScenePresence> avatars = GetLinkAvatars(linknumber); 8667 List<ScenePresence> avatars;
8881 8668
8882 LSL_List res = new LSL_List(); 8669 LSL_List res = new LSL_List();
8670 LSL_List remaining = null;
8883 8671
8884 if (parts.Count > 0) 8672 while (rules.Length > 0)
8885 { 8673 {
8886 foreach (var part in parts) 8674 parts = GetLinkParts(linknumber);
8675 avatars = GetLinkAvatars(linknumber);
8676
8677 remaining = null;
8678 foreach (SceneObjectPart part in parts)
8887 { 8679 {
8888 LSL_List partRes = GetLinkPrimitiveParams(part, rules); 8680 remaining = GetPrimParams(part, rules, ref res);
8889 res += partRes;
8890 } 8681 }
8891 }
8892 if (avatars.Count > 0)
8893 {
8894 foreach (ScenePresence avatar in avatars) 8682 foreach (ScenePresence avatar in avatars)
8895 { 8683 {
8896 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); 8684 remaining = GetPrimParams(avatar, rules, ref res);
8897 res += avaRes;
8898 } 8685 }
8899 }
8900 return res;
8901 }
8902
8903 public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules)
8904 {
8905 // avatars case
8906 // replies as SL wiki
8907
8908 LSL_List res = new LSL_List();
8909// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
8910 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
8911 8686
8912 int idx = 0; 8687 if (remaining != null && remaining.Length > 0)
8913 while (idx < rules.Length)
8914 {
8915 int code = (int)rules.GetLSLIntegerItem(idx++);
8916 int remain = rules.Length - idx;
8917
8918 switch (code)
8919 { 8688 {
8920 case (int)ScriptBaseClass.PRIM_MATERIAL: 8689 linknumber = remaining.GetLSLIntegerItem(0);
8921 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); 8690 rules = remaining.GetSublist(1, -1);
8922 break;
8923
8924 case (int)ScriptBaseClass.PRIM_PHYSICS:
8925 res.Add(new LSL_Integer(0));
8926 break;
8927
8928 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8929 res.Add(new LSL_Integer(0));
8930 break;
8931
8932 case (int)ScriptBaseClass.PRIM_PHANTOM:
8933 res.Add(new LSL_Integer(0));
8934 break;
8935
8936 case (int)ScriptBaseClass.PRIM_POSITION:
8937
8938 Vector3 pos = avatar.OffsetPosition;
8939
8940 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
8941 pos -= sitOffset;
8942
8943 if( sitPart != null)
8944 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
8945
8946 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
8947 break;
8948
8949 case (int)ScriptBaseClass.PRIM_SIZE:
8950 // as in llGetAgentSize above
8951 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
8952 break;
8953
8954 case (int)ScriptBaseClass.PRIM_ROTATION:
8955 Quaternion rot = avatar.Rotation;
8956 if (sitPart != null)
8957 {
8958 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
8959 }
8960
8961 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
8962 break;
8963
8964 case (int)ScriptBaseClass.PRIM_TYPE:
8965 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8966 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8967 res.Add(new LSL_Vector(0f,1.0f,0f));
8968 res.Add(new LSL_Float(0.0f));
8969 res.Add(new LSL_Vector(0, 0, 0));
8970 res.Add(new LSL_Vector(1.0f,1.0f,0f));
8971 res.Add(new LSL_Vector(0, 0, 0));
8972 break;
8973
8974 case (int)ScriptBaseClass.PRIM_TEXTURE:
8975 if (remain < 1)
8976 return res;
8977
8978 int face = (int)rules.GetLSLIntegerItem(idx++);
8979 if (face == ScriptBaseClass.ALL_SIDES)
8980 {
8981 for (face = 0; face < 21; face++)
8982 {
8983 res.Add(new LSL_String(""));
8984 res.Add(new LSL_Vector(0,0,0));
8985 res.Add(new LSL_Vector(0,0,0));
8986 res.Add(new LSL_Float(0.0));
8987 }
8988 }
8989 else
8990 {
8991 if (face >= 0 && face < 21)
8992 {
8993 res.Add(new LSL_String(""));
8994 res.Add(new LSL_Vector(0,0,0));
8995 res.Add(new LSL_Vector(0,0,0));
8996 res.Add(new LSL_Float(0.0));
8997 }
8998 }
8999 break;
9000
9001 case (int)ScriptBaseClass.PRIM_COLOR:
9002 if (remain < 1)
9003 return res;
9004
9005 face = (int)rules.GetLSLIntegerItem(idx++);
9006
9007 if (face == ScriptBaseClass.ALL_SIDES)
9008 {
9009 for (face = 0; face < 21; face++)
9010 {
9011 res.Add(new LSL_Vector(0,0,0));
9012 res.Add(new LSL_Float(0));
9013 }
9014 }
9015 else
9016 {
9017 res.Add(new LSL_Vector(0,0,0));
9018 res.Add(new LSL_Float(0));
9019 }
9020 break;
9021
9022 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9023 if (remain < 1)
9024 return res;
9025 face = (int)rules.GetLSLIntegerItem(idx++);
9026
9027 if (face == ScriptBaseClass.ALL_SIDES)
9028 {
9029 for (face = 0; face < 21; face++)
9030 {
9031 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9032 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9033 }
9034 }
9035 else
9036 {
9037 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9038 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9039 }
9040 break;
9041
9042 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9043 if (remain < 1)
9044 return res;
9045 face = (int)rules.GetLSLIntegerItem(idx++);
9046
9047 if (face == ScriptBaseClass.ALL_SIDES)
9048 {
9049 for (face = 0; face < 21; face++)
9050 {
9051 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9052 }
9053 }
9054 else
9055 {
9056 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9057 }
9058 break;
9059
9060 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
9061 res.Add(new LSL_Integer(0));
9062 res.Add(new LSL_Integer(0));// softness
9063 res.Add(new LSL_Float(0.0f)); // gravity
9064 res.Add(new LSL_Float(0.0f)); // friction
9065 res.Add(new LSL_Float(0.0f)); // wind
9066 res.Add(new LSL_Float(0.0f)); // tension
9067 res.Add(new LSL_Vector(0f,0f,0f));
9068 break;
9069
9070 case (int)ScriptBaseClass.PRIM_TEXGEN:
9071 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9072 if (remain < 1)
9073 return res;
9074 face = (int)rules.GetLSLIntegerItem(idx++);
9075
9076 if (face == ScriptBaseClass.ALL_SIDES)
9077 {
9078 for (face = 0; face < 21; face++)
9079 {
9080 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9081 }
9082 }
9083 else
9084 {
9085 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9086 }
9087 break;
9088
9089 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
9090 res.Add(new LSL_Integer(0));
9091 res.Add(new LSL_Vector(0f,0f,0f));
9092 res.Add(new LSL_Float(0f)); // intensity
9093 res.Add(new LSL_Float(0f)); // radius
9094 res.Add(new LSL_Float(0f)); // falloff
9095 break;
9096
9097 case (int)ScriptBaseClass.PRIM_GLOW:
9098 if (remain < 1)
9099 return res;
9100 face = (int)rules.GetLSLIntegerItem(idx++);
9101
9102 if (face == ScriptBaseClass.ALL_SIDES)
9103 {
9104 for (face = 0; face < 21; face++)
9105 {
9106 res.Add(new LSL_Float(0f));
9107 }
9108 }
9109 else
9110 {
9111 res.Add(new LSL_Float(0f));
9112 }
9113 break;
9114
9115 case (int)ScriptBaseClass.PRIM_TEXT:
9116 res.Add(new LSL_String(""));
9117 res.Add(new LSL_Vector(0f,0f,0f));
9118 res.Add(new LSL_Float(1.0f));
9119 break;
9120
9121 case (int)ScriptBaseClass.PRIM_NAME:
9122 res.Add(new LSL_String(avatar.Name));
9123 break;
9124
9125 case (int)ScriptBaseClass.PRIM_DESC:
9126 res.Add(new LSL_String(""));
9127 break;
9128
9129 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
9130 Quaternion lrot = avatar.Rotation;
9131
9132 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9133 {
9134 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
9135 }
9136 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
9137 break;
9138
9139 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9140 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
9141 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
9142 lpos -= lsitOffset;
9143
9144 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9145 {
9146 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
9147 }
9148 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
9149 break;
9150
9151 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9152 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9153 return res;
9154 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9155 LSL_List new_rules = rules.GetSublist(idx, -1);
9156
9157 res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9158 return res;
9159 } 8691 }
9160 } 8692 }
8693
9161 return res; 8694 return res;
9162 } 8695 }
9163 8696
9164 public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) 8697 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
9165 { 8698 {
9166 LSL_List res = new LSL_List();
9167 int idx=0; 8699 int idx=0;
9168 while (idx < rules.Length) 8700 while (idx < rules.Length)
9169 { 8701 {
@@ -9301,7 +8833,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9301 8833
9302 case (int)ScriptBaseClass.PRIM_TEXTURE: 8834 case (int)ScriptBaseClass.PRIM_TEXTURE:
9303 if (remain < 1) 8835 if (remain < 1)
9304 return res; 8836 return null;
9305 8837
9306 int face = (int)rules.GetLSLIntegerItem(idx++); 8838 int face = (int)rules.GetLSLIntegerItem(idx++);
9307 Primitive.TextureEntry tex = part.Shape.Textures; 8839 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -9341,7 +8873,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9341 8873
9342 case (int)ScriptBaseClass.PRIM_COLOR: 8874 case (int)ScriptBaseClass.PRIM_COLOR:
9343 if (remain < 1) 8875 if (remain < 1)
9344 return res; 8876 return null;
9345 8877
9346 face=(int)rules.GetLSLIntegerItem(idx++); 8878 face=(int)rules.GetLSLIntegerItem(idx++);
9347 8879
@@ -9370,7 +8902,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9370 8902
9371 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8903 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9372 if (remain < 1) 8904 if (remain < 1)
9373 return res; 8905 return null;
8906
9374 face = (int)rules.GetLSLIntegerItem(idx++); 8907 face = (int)rules.GetLSLIntegerItem(idx++);
9375 8908
9376 tex = part.Shape.Textures; 8909 tex = part.Shape.Textures;
@@ -9426,7 +8959,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9426 8959
9427 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8960 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9428 if (remain < 1) 8961 if (remain < 1)
9429 return res; 8962 return null;
8963
9430 face = (int)rules.GetLSLIntegerItem(idx++); 8964 face = (int)rules.GetLSLIntegerItem(idx++);
9431 8965
9432 tex = part.Shape.Textures; 8966 tex = part.Shape.Textures;
@@ -9480,7 +9014,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9480 case (int)ScriptBaseClass.PRIM_TEXGEN: 9014 case (int)ScriptBaseClass.PRIM_TEXGEN:
9481 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 9015 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9482 if (remain < 1) 9016 if (remain < 1)
9483 return res; 9017 return null;
9018
9484 face = (int)rules.GetLSLIntegerItem(idx++); 9019 face = (int)rules.GetLSLIntegerItem(idx++);
9485 9020
9486 tex = part.Shape.Textures; 9021 tex = part.Shape.Textures;
@@ -9528,7 +9063,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9528 9063
9529 case (int)ScriptBaseClass.PRIM_GLOW: 9064 case (int)ScriptBaseClass.PRIM_GLOW:
9530 if (remain < 1) 9065 if (remain < 1)
9531 return res; 9066 return null;
9067
9532 face = (int)rules.GetLSLIntegerItem(idx++); 9068 face = (int)rules.GetLSLIntegerItem(idx++);
9533 9069
9534 tex = part.Shape.Textures; 9070 tex = part.Shape.Textures;
@@ -9572,18 +9108,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9572 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9108 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9573 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9109 res.Add(new LSL_Vector(GetPartLocalPos(part)));
9574 break; 9110 break;
9575 9111 case (int)ScriptBaseClass.PRIM_SLICE:
9112 PrimType prim_type = part.GetPrimType();
9113 bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
9114 res.Add(new LSL_Vector(
9115 (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
9116 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
9117 0
9118 ));
9119 break;
9576 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9120 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9577 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 9121 if(remain < 3)
9578 return res; 9122 return null;
9579 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); 9123
9580 LSL_List new_rules = rules.GetSublist(idx, -1); 9124 return rules.GetSublist(idx, -1);
9581 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9582 res += tres;
9583 return res;
9584 } 9125 }
9585 } 9126 }
9586 return res; 9127
9128 return null;
9587 } 9129 }
9588 9130
9589 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 9131 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
@@ -10983,20 +10525,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10983 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) 10525 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
10984 { 10526 {
10985 case ParcelMediaCommandEnum.Url: 10527 case ParcelMediaCommandEnum.Url:
10986 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10528 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
10987 break; 10529 break;
10988 case ParcelMediaCommandEnum.Desc: 10530 case ParcelMediaCommandEnum.Desc:
10989 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); 10531 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
10990 break; 10532 break;
10991 case ParcelMediaCommandEnum.Texture: 10533 case ParcelMediaCommandEnum.Texture:
10992 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); 10534 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
10993 break; 10535 break;
10994 case ParcelMediaCommandEnum.Type: 10536 case ParcelMediaCommandEnum.Type:
10995 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); 10537 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
10996 break; 10538 break;
10997 case ParcelMediaCommandEnum.Size: 10539 case ParcelMediaCommandEnum.Size:
10998 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); 10540 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
10999 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); 10541 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
11000 break; 10542 break;
11001 default: 10543 default:
11002 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 10544 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
@@ -11166,9 +10708,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11166 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10708 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
11167 if (avatar != null) 10709 if (avatar != null)
11168 { 10710 {
11169 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, 10711 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
11170 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10712 simname, pos, lookAt);
11171 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
11172 } 10713 }
11173 10714
11174 ScriptSleep(1000); 10715 ScriptSleep(1000);
@@ -11353,31 +10894,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11353 public LSL_Float llListStatistics(int operation, LSL_List src) 10894 public LSL_Float llListStatistics(int operation, LSL_List src)
11354 { 10895 {
11355 m_host.AddScriptLPS(1); 10896 m_host.AddScriptLPS(1);
11356 LSL_List nums = LSL_List.ToDoubleList(src);
11357 switch (operation) 10897 switch (operation)
11358 { 10898 {
11359 case ScriptBaseClass.LIST_STAT_RANGE: 10899 case ScriptBaseClass.LIST_STAT_RANGE:
11360 return nums.Range(); 10900 return src.Range();
11361 case ScriptBaseClass.LIST_STAT_MIN: 10901 case ScriptBaseClass.LIST_STAT_MIN:
11362 return nums.Min(); 10902 return src.Min();
11363 case ScriptBaseClass.LIST_STAT_MAX: 10903 case ScriptBaseClass.LIST_STAT_MAX:
11364 return nums.Max(); 10904 return src.Max();
11365 case ScriptBaseClass.LIST_STAT_MEAN: 10905 case ScriptBaseClass.LIST_STAT_MEAN:
11366 return nums.Mean(); 10906 return src.Mean();
11367 case ScriptBaseClass.LIST_STAT_MEDIAN: 10907 case ScriptBaseClass.LIST_STAT_MEDIAN:
11368 return nums.Median(); 10908 return LSL_List.ToDoubleList(src).Median();
11369 case ScriptBaseClass.LIST_STAT_NUM_COUNT: 10909 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
11370 return nums.NumericLength(); 10910 return src.NumericLength();
11371 case ScriptBaseClass.LIST_STAT_STD_DEV: 10911 case ScriptBaseClass.LIST_STAT_STD_DEV:
11372 return nums.StdDev(); 10912 return src.StdDev();
11373 case ScriptBaseClass.LIST_STAT_SUM: 10913 case ScriptBaseClass.LIST_STAT_SUM:
11374 return nums.Sum(); 10914 return src.Sum();
11375 case ScriptBaseClass.LIST_STAT_SUM_SQUARES: 10915 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
11376 return nums.SumSqrs(); 10916 return src.SumSqrs();
11377 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: 10917 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
11378 return nums.GeometricMean(); 10918 return src.GeometricMean();
11379 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: 10919 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
11380 return nums.HarmonicMean(); 10920 return src.HarmonicMean();
11381 default: 10921 default:
11382 return 0.0; 10922 return 0.0;
11383 } 10923 }
@@ -11735,7 +11275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11735 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) 11275 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
11736 { 11276 {
11737 m_host.AddScriptLPS(1); 11277 m_host.AddScriptLPS(1);
11738 LandData land = World.GetLandData((float)pos.x, (float)pos.y); 11278 LandData land = World.GetLandData(pos);
11739 if (land == null) 11279 if (land == null)
11740 { 11280 {
11741 return new LSL_List(0); 11281 return new LSL_List(0);
@@ -11903,13 +11443,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11903 else 11443 else
11904 rot = obj.GetWorldRotation(); 11444 rot = obj.GetWorldRotation();
11905 11445
11906 LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); 11446 LSL_Rotation objrot = new LSL_Rotation(rot);
11907 ret.Add(objrot); 11447 ret.Add(objrot);
11908 } 11448 }
11909 break; 11449 break;
11910 case ScriptBaseClass.OBJECT_VELOCITY: 11450 case ScriptBaseClass.OBJECT_VELOCITY:
11911 Vector3 ovel = obj.Velocity; 11451 ret.Add(new LSL_Vector(obj.Velocity));
11912 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
11913 break; 11452 break;
11914 case ScriptBaseClass.OBJECT_OWNER: 11453 case ScriptBaseClass.OBJECT_OWNER:
11915 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11454 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -12122,7 +11661,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12122 return tid.ToString(); 11661 return tid.ToString();
12123 } 11662 }
12124 11663
12125 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11664 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
12126 { 11665 {
12127 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11666 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12128 if (obj == null) 11667 if (obj == null)
@@ -12131,28 +11670,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12131 if (obj.OwnerID != m_host.OwnerID) 11670 if (obj.OwnerID != m_host.OwnerID)
12132 return; 11671 return;
12133 11672
12134 LSL_List remaining = SetPrimParams(obj, rules); 11673 uint rulesParsed = 0;
11674 LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
12135 11675
12136 while ((object)remaining != null && remaining.Length > 2) 11676 while ((object)remaining != null && remaining.Length > 2)
12137 { 11677 {
12138 LSL_Integer newLink = remaining.GetLSLIntegerItem(0); 11678 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
12139 LSL_List newrules = remaining.GetSublist(1, -1); 11679 LSL_List newrules = remaining.GetSublist(1, -1);
12140 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ 11680 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
12141 remaining = SetPrimParams(part, newrules); 11681 remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
12142 } 11682 }
12143 } 11683 }
12144 } 11684 }
12145 11685
12146 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11686 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
12147 { 11687 {
12148 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11688 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12149 if (obj == null)
12150 return new LSL_List();
12151 11689
12152 if (obj.OwnerID != m_host.OwnerID) 11690 LSL_List result = new LSL_List();
12153 return new LSL_List(); 11691
11692 if (obj != null && obj.OwnerID != m_host.OwnerID)
11693 {
11694 LSL_List remaining = GetPrimParams(obj, rules, ref result);
11695
11696 while (remaining != null && remaining.Length > 2)
11697 {
11698 int linknumber = remaining.GetLSLIntegerItem(0);
11699 rules = remaining.GetSublist(1, -1);
11700 List<SceneObjectPart> parts = GetLinkParts(linknumber);
11701
11702 foreach (SceneObjectPart part in parts)
11703 remaining = GetPrimParams(part, rules, ref result);
11704 }
11705 }
12154 11706
12155 return GetLinkPrimitiveParams(obj, rules); 11707 return result;
12156 } 11708 }
12157 11709
12158 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 11710 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
@@ -12515,8 +12067,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12515 12067
12516 m_host.AddScriptLPS(1); 12068 m_host.AddScriptLPS(1);
12517 12069
12518 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); 12070 Vector3 rayStart = start;
12519 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); 12071 Vector3 rayEnd = end;
12520 Vector3 dir = rayEnd - rayStart; 12072 Vector3 dir = rayEnd - rayStart;
12521 12073
12522 float dist = Vector3.Mag(dir); 12074 float dist = Vector3.Mag(dir);
@@ -13090,6 +12642,455 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13090 } 12642 }
13091 } 12643 }
13092 } 12644 }
12645
12646 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12647 {
12648 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12649
12650 int idx = 0;
12651 int idxStart = 0;
12652
12653 bool positionChanged = false;
12654 Vector3 finalPos = Vector3.Zero;
12655
12656 try
12657 {
12658 while (idx < rules.Length)
12659 {
12660 ++rulesParsed;
12661 int code = rules.GetLSLIntegerItem(idx++);
12662
12663 int remain = rules.Length - idx;
12664 idxStart = idx;
12665
12666 switch (code)
12667 {
12668 case (int)ScriptBaseClass.PRIM_POSITION:
12669 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12670 {
12671 if (remain < 1)
12672 return null;
12673
12674 LSL_Vector v;
12675 v = rules.GetVector3Item(idx++);
12676
12677 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12678 if (part == null)
12679 break;
12680
12681 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12682 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12683 if (part.LinkNum > 1)
12684 {
12685 localRot = GetPartLocalRot(part);
12686 localPos = GetPartLocalPos(part);
12687 }
12688
12689 v -= localPos;
12690 v /= localRot;
12691
12692 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12693
12694 v = v + 2 * sitOffset;
12695
12696 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12697 av.SendAvatarDataToAllAgents();
12698
12699 }
12700 break;
12701
12702 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12703 case (int)ScriptBaseClass.PRIM_ROTATION:
12704 {
12705 if (remain < 1)
12706 return null;
12707
12708 LSL_Rotation r;
12709 r = rules.GetQuaternionItem(idx++);
12710
12711 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12712 if (part == null)
12713 break;
12714
12715 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12716 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12717
12718 if (part.LinkNum > 1)
12719 localRot = GetPartLocalRot(part);
12720
12721 r = r * llGetRootRotation() / localRot;
12722 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12723 av.SendAvatarDataToAllAgents();
12724 }
12725 break;
12726
12727 // parse rest doing nothing but number of parameters error check
12728 case (int)ScriptBaseClass.PRIM_SIZE:
12729 case (int)ScriptBaseClass.PRIM_MATERIAL:
12730 case (int)ScriptBaseClass.PRIM_PHANTOM:
12731 case (int)ScriptBaseClass.PRIM_PHYSICS:
12732 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12733 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12734 case (int)ScriptBaseClass.PRIM_NAME:
12735 case (int)ScriptBaseClass.PRIM_DESC:
12736 if (remain < 1)
12737 return null;
12738 idx++;
12739 break;
12740
12741 case (int)ScriptBaseClass.PRIM_GLOW:
12742 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12743 case (int)ScriptBaseClass.PRIM_TEXGEN:
12744 if (remain < 2)
12745 return null;
12746 idx += 2;
12747 break;
12748
12749 case (int)ScriptBaseClass.PRIM_TYPE:
12750 if (remain < 3)
12751 return null;
12752 code = (int)rules.GetLSLIntegerItem(idx++);
12753 remain = rules.Length - idx;
12754 switch (code)
12755 {
12756 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12757 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12758 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12759 if (remain < 6)
12760 return null;
12761 idx += 6;
12762 break;
12763
12764 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12765 if (remain < 5)
12766 return null;
12767 idx += 5;
12768 break;
12769
12770 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12771 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12772 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12773 if (remain < 11)
12774 return null;
12775 idx += 11;
12776 break;
12777
12778 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12779 if (remain < 2)
12780 return null;
12781 idx += 2;
12782 break;
12783 }
12784 break;
12785
12786 case (int)ScriptBaseClass.PRIM_COLOR:
12787 case (int)ScriptBaseClass.PRIM_TEXT:
12788 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12789 case (int)ScriptBaseClass.PRIM_OMEGA:
12790 if (remain < 3)
12791 return null;
12792 idx += 3;
12793 break;
12794
12795 case (int)ScriptBaseClass.PRIM_TEXTURE:
12796 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12797 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12798 if (remain < 5)
12799 return null;
12800 idx += 5;
12801 break;
12802
12803 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12804 if (remain < 7)
12805 return null;
12806
12807 idx += 7;
12808 break;
12809
12810 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12811 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12812 return null;
12813
12814 return rules.GetSublist(idx, -1);
12815 }
12816 }
12817 }
12818 catch (InvalidCastException e)
12819 {
12820 ShoutError(string.Format(
12821 "{0} error running rule #{1}: arg #{2} ",
12822 originFunc, rulesParsed, idx - idxStart) + e.Message);
12823 }
12824 finally
12825 {
12826 if (positionChanged)
12827 {
12828 av.OffsetPosition = finalPos;
12829// av.SendAvatarDataToAllAgents();
12830 av.SendTerseUpdateToAllClients();
12831 positionChanged = false;
12832 }
12833 }
12834 return null;
12835 }
12836
12837 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
12838 {
12839 // avatars case
12840 // replies as SL wiki
12841
12842// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
12843 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
12844
12845 int idx = 0;
12846 while (idx < rules.Length)
12847 {
12848 int code = (int)rules.GetLSLIntegerItem(idx++);
12849 int remain = rules.Length - idx;
12850
12851 switch (code)
12852 {
12853 case (int)ScriptBaseClass.PRIM_MATERIAL:
12854 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
12855 break;
12856
12857 case (int)ScriptBaseClass.PRIM_PHYSICS:
12858 res.Add(new LSL_Integer(0));
12859 break;
12860
12861 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12862 res.Add(new LSL_Integer(0));
12863 break;
12864
12865 case (int)ScriptBaseClass.PRIM_PHANTOM:
12866 res.Add(new LSL_Integer(0));
12867 break;
12868
12869 case (int)ScriptBaseClass.PRIM_POSITION:
12870
12871 Vector3 pos = avatar.OffsetPosition;
12872
12873 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
12874 pos -= sitOffset;
12875
12876 if( sitPart != null)
12877 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
12878
12879 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
12880 break;
12881
12882 case (int)ScriptBaseClass.PRIM_SIZE:
12883 // as in llGetAgentSize above
12884 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
12885 break;
12886
12887 case (int)ScriptBaseClass.PRIM_ROTATION:
12888 Quaternion rot = avatar.Rotation;
12889 if (sitPart != null)
12890 {
12891 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
12892 }
12893
12894 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
12895 break;
12896
12897 case (int)ScriptBaseClass.PRIM_TYPE:
12898 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
12899 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
12900 res.Add(new LSL_Vector(0f,1.0f,0f));
12901 res.Add(new LSL_Float(0.0f));
12902 res.Add(new LSL_Vector(0, 0, 0));
12903 res.Add(new LSL_Vector(1.0f,1.0f,0f));
12904 res.Add(new LSL_Vector(0, 0, 0));
12905 break;
12906
12907 case (int)ScriptBaseClass.PRIM_TEXTURE:
12908 if (remain < 1)
12909 return null;
12910
12911 int face = (int)rules.GetLSLIntegerItem(idx++);
12912 if (face == ScriptBaseClass.ALL_SIDES)
12913 {
12914 for (face = 0; face < 21; face++)
12915 {
12916 res.Add(new LSL_String(""));
12917 res.Add(new LSL_Vector(0,0,0));
12918 res.Add(new LSL_Vector(0,0,0));
12919 res.Add(new LSL_Float(0.0));
12920 }
12921 }
12922 else
12923 {
12924 if (face >= 0 && face < 21)
12925 {
12926 res.Add(new LSL_String(""));
12927 res.Add(new LSL_Vector(0,0,0));
12928 res.Add(new LSL_Vector(0,0,0));
12929 res.Add(new LSL_Float(0.0));
12930 }
12931 }
12932 break;
12933
12934 case (int)ScriptBaseClass.PRIM_COLOR:
12935 if (remain < 1)
12936 return null;
12937
12938 face = (int)rules.GetLSLIntegerItem(idx++);
12939
12940 if (face == ScriptBaseClass.ALL_SIDES)
12941 {
12942 for (face = 0; face < 21; face++)
12943 {
12944 res.Add(new LSL_Vector(0,0,0));
12945 res.Add(new LSL_Float(0));
12946 }
12947 }
12948 else
12949 {
12950 res.Add(new LSL_Vector(0,0,0));
12951 res.Add(new LSL_Float(0));
12952 }
12953 break;
12954
12955 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12956 if (remain < 1)
12957 return null;
12958 face = (int)rules.GetLSLIntegerItem(idx++);
12959
12960 if (face == ScriptBaseClass.ALL_SIDES)
12961 {
12962 for (face = 0; face < 21; face++)
12963 {
12964 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12965 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12966 }
12967 }
12968 else
12969 {
12970 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12971 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12972 }
12973 break;
12974
12975 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12976 if (remain < 1)
12977 return null;
12978 face = (int)rules.GetLSLIntegerItem(idx++);
12979
12980 if (face == ScriptBaseClass.ALL_SIDES)
12981 {
12982 for (face = 0; face < 21; face++)
12983 {
12984 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
12985 }
12986 }
12987 else
12988 {
12989 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
12990 }
12991 break;
12992
12993 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12994 res.Add(new LSL_Integer(0));
12995 res.Add(new LSL_Integer(0));// softness
12996 res.Add(new LSL_Float(0.0f)); // gravity
12997 res.Add(new LSL_Float(0.0f)); // friction
12998 res.Add(new LSL_Float(0.0f)); // wind
12999 res.Add(new LSL_Float(0.0f)); // tension
13000 res.Add(new LSL_Vector(0f,0f,0f));
13001 break;
13002
13003 case (int)ScriptBaseClass.PRIM_TEXGEN:
13004 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13005 if (remain < 1)
13006 return null;
13007 face = (int)rules.GetLSLIntegerItem(idx++);
13008
13009 if (face == ScriptBaseClass.ALL_SIDES)
13010 {
13011 for (face = 0; face < 21; face++)
13012 {
13013 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13014 }
13015 }
13016 else
13017 {
13018 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13019 }
13020 break;
13021
13022 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13023 res.Add(new LSL_Integer(0));
13024 res.Add(new LSL_Vector(0f,0f,0f));
13025 res.Add(new LSL_Float(0f)); // intensity
13026 res.Add(new LSL_Float(0f)); // radius
13027 res.Add(new LSL_Float(0f)); // falloff
13028 break;
13029
13030 case (int)ScriptBaseClass.PRIM_GLOW:
13031 if (remain < 1)
13032 return null;
13033 face = (int)rules.GetLSLIntegerItem(idx++);
13034
13035 if (face == ScriptBaseClass.ALL_SIDES)
13036 {
13037 for (face = 0; face < 21; face++)
13038 {
13039 res.Add(new LSL_Float(0f));
13040 }
13041 }
13042 else
13043 {
13044 res.Add(new LSL_Float(0f));
13045 }
13046 break;
13047
13048 case (int)ScriptBaseClass.PRIM_TEXT:
13049 res.Add(new LSL_String(""));
13050 res.Add(new LSL_Vector(0f,0f,0f));
13051 res.Add(new LSL_Float(1.0f));
13052 break;
13053
13054 case (int)ScriptBaseClass.PRIM_NAME:
13055 res.Add(new LSL_String(avatar.Name));
13056 break;
13057
13058 case (int)ScriptBaseClass.PRIM_DESC:
13059 res.Add(new LSL_String(""));
13060 break;
13061
13062 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13063 Quaternion lrot = avatar.Rotation;
13064
13065 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13066 {
13067 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13068 }
13069 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13070 break;
13071
13072 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13073 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13074 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13075 lpos -= lsitOffset;
13076
13077 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13078 {
13079 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13080 }
13081 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13082 break;
13083
13084 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13085 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13086 return null;
13087
13088 return rules.GetSublist(idx, -1);
13089 }
13090 }
13091
13092 return null;
13093 }
13093 } 13094 }
13094 13095
13095 public class NotecardCache 13096 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 795de80..ceb4660 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: 304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
305 idx++; 305 idx++;
306 iV = rules.GetVector3Item(idx); 306 iV = rules.GetVector3Item(idx);
307 wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 307 wl.cloudDetailXYDensity = iV;
308 break; 308 break;
309 case (int)ScriptBaseClass.WL_CLOUD_SCALE: 309 case (int)ScriptBaseClass.WL_CLOUD_SCALE:
310 idx++; 310 idx++;
@@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: 329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
330 idx++; 330 idx++;
331 iV = rules.GetVector3Item(idx); 331 iV = rules.GetVector3Item(idx);
332 wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 332 wl.cloudXYDensity = iV;
333 break; 333 break;
334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: 334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
335 idx++; 335 idx++;
@@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: 384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
385 idx++; 385 idx++;
386 iV = rules.GetVector3Item(idx); 386 iV = rules.GetVector3Item(idx);
387 wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 387 wl.reflectionWaveletScale = iV;
388 break; 388 break;
389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: 389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
390 idx++; 390 idx++;
@@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
422 case (int)ScriptBaseClass.WL_WATER_COLOR: 422 case (int)ScriptBaseClass.WL_WATER_COLOR:
423 idx++; 423 idx++;
424 iV = rules.GetVector3Item(idx); 424 iV = rules.GetVector3Item(idx);
425 wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 425 wl.waterColor = iV;
426 break; 426 break;
427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: 427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
428 idx++; 428 idx++;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 7844c75..6809c09 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 254
255 object[] convertedParms = new object[parms.Length]; 255 object[] convertedParms = new object[parms.Length];
256 for (int i = 0; i < parms.Length; i++) 256 for (int i = 0; i < parms.Length; i++)
257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); 257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
258 258
259 // now call the function, the contract with the function is that it will always return 259 // now call the function, the contract with the function is that it will always return
260 // non-null but don't trust it completely 260 // non-null but don't trust it completely
@@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
294 294
295 /// <summary> 295 /// <summary>
296 /// </summary> 296 /// </summary>
297 protected object ConvertFromLSL(object lslparm, Type type) 297 protected object ConvertFromLSL(object lslparm, Type type, string fname)
298 { 298 {
299 // ---------- String ---------- 299 // ---------- String ----------
300 if (lslparm is LSL_String) 300 if (lslparm is LSL_String)
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
310 // ---------- Integer ---------- 310 // ---------- Integer ----------
311 else if (lslparm is LSL_Integer) 311 else if (lslparm is LSL_Integer)
312 { 312 {
313 if (type == typeof(int)) 313 if (type == typeof(int) || type == typeof(float))
314 return (int)(LSL_Integer)lslparm; 314 return (int)(LSL_Integer)lslparm;
315 } 315 }
316 316
@@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
333 { 333 {
334 if (type == typeof(OpenMetaverse.Quaternion)) 334 if (type == typeof(OpenMetaverse.Quaternion))
335 { 335 {
336 LSL_Rotation rot = (LSL_Rotation)lslparm; 336 return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
337 return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
338 } 337 }
339 } 338 }
340 339
@@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
343 { 342 {
344 if (type == typeof(OpenMetaverse.Vector3)) 343 if (type == typeof(OpenMetaverse.Vector3))
345 { 344 {
346 LSL_Vector vect = (LSL_Vector)lslparm; 345 return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
347 return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
348 } 346 }
349 } 347 }
350 348
@@ -367,23 +365,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
367 result[i] = new UUID((LSL_Key)plist[i]); 365 result[i] = new UUID((LSL_Key)plist[i]);
368 else if (plist[i] is LSL_Rotation) 366 else if (plist[i] is LSL_Rotation)
369 { 367 {
370 LSL_Rotation rot = (LSL_Rotation)plist[i]; 368 result[i] = (OpenMetaverse.Quaternion)(
371 result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); 369 (LSL_Rotation)plist[i]);
372 } 370 }
373 else if (plist[i] is LSL_Vector) 371 else if (plist[i] is LSL_Vector)
374 { 372 {
375 LSL_Vector vect = (LSL_Vector)plist[i]; 373 result[i] = (OpenMetaverse.Vector3)(
376 result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); 374 (LSL_Vector)plist[i]);
377 } 375 }
378 else 376 else
379 MODError("unknown LSL list element type"); 377 MODError(String.Format("{0}: unknown LSL list element type", fname));
380 } 378 }
381 379
382 return result; 380 return result;
383 } 381 }
384 } 382 }
385 383
386 MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); 384 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
387 return null; 385 return null;
388 } 386 }
389 387
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 2f02f1f..160e2df 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -141,6 +141,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 internal bool m_debuggerSafe = false; 141 internal bool m_debuggerSafe = false;
142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
143 143
144 protected IUrlModule m_UrlModule = null;
145
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
145 { 147 {
146 m_ScriptEngine = ScriptEngine; 148 m_ScriptEngine = ScriptEngine;
@@ -148,6 +150,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
148 m_item = item; 150 m_item = item;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
150 152
153 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
154
151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 155 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
152 m_OSFunctionsEnabled = true; 156 m_OSFunctionsEnabled = true;
153 157
@@ -782,10 +786,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
782 786
783 // We will launch the teleport on a new thread so that when the script threads are terminated 787 // We will launch the teleport on a new thread so that when the script threads are terminated
784 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 788 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
785 Util.FireAndForget( 789 Util.FireAndForget(o => World.RequestTeleportLocation(
786 o => World.RequestTeleportLocation(presence.ControllingClient, regionName, 790 presence.ControllingClient, regionName, position,
787 new Vector3((float)position.x, (float)position.y, (float)position.z), 791 lookat, (uint)TPFlags.ViaLocation));
788 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
789 792
790 ScriptSleep(5000); 793 ScriptSleep(5000);
791 794
@@ -828,10 +831,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
828 831
829 // We will launch the teleport on a new thread so that when the script threads are terminated 832 // We will launch the teleport on a new thread so that when the script threads are terminated
830 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 833 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
831 Util.FireAndForget( 834 Util.FireAndForget(o => World.RequestTeleportLocation(
832 o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, 835 presence.ControllingClient, regionHandle,
833 new Vector3((float)position.x, (float)position.y, (float)position.z), 836 position, lookat, (uint)TPFlags.ViaLocation));
834 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
835 837
836 ScriptSleep(5000); 838 ScriptSleep(5000);
837 839
@@ -1680,6 +1682,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1680 return; 1682 return;
1681 } 1683 }
1682 1684
1685 MessageObject(objUUID, message);
1686 }
1687
1688 private void MessageObject(UUID objUUID, string message)
1689 {
1683 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; 1690 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1684 1691
1685 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); 1692 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@@ -2259,11 +2266,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2259 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); 2266 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
2260 m_host.AddScriptLPS(1); 2267 m_host.AddScriptLPS(1);
2261 InitLSL(); 2268 InitLSL();
2269 // One needs to cast m_LSL_Api because we're using functions not
2270 // on the ILSL_Api interface.
2271 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
2262 LSL_List retVal = new LSL_List(); 2272 LSL_List retVal = new LSL_List();
2263 List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); 2273 LSL_List remaining = null;
2274 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2264 foreach (SceneObjectPart part in parts) 2275 foreach (SceneObjectPart part in parts)
2265 { 2276 {
2266 retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); 2277 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2278 }
2279
2280 while (remaining != null && remaining.Length > 2)
2281 {
2282 linknumber = remaining.GetLSLIntegerItem(0);
2283 rules = remaining.GetSublist(1, -1);
2284 parts = LSL_Api.GetLinkParts(linknumber);
2285
2286 foreach (SceneObjectPart part in parts)
2287 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2267 } 2288 }
2268 return retVal; 2289 return retVal;
2269 } 2290 }
@@ -2355,7 +2376,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2355 ownerID = m_host.OwnerID; 2376 ownerID = m_host.OwnerID;
2356 UUID x = module.CreateNPC(firstname, 2377 UUID x = module.CreateNPC(firstname,
2357 lastname, 2378 lastname,
2358 new Vector3((float) position.x, (float) position.y, (float) position.z), 2379 position,
2359 ownerID, 2380 ownerID,
2360 senseAsAgent, 2381 senseAsAgent,
2361 World, 2382 World,
@@ -2478,7 +2499,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2478 return new LSL_Vector(0, 0, 0); 2499 return new LSL_Vector(0, 0, 0);
2479 } 2500 }
2480 2501
2481 public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) 2502 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
2482 { 2503 {
2483 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); 2504 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
2484 m_host.AddScriptLPS(1); 2505 m_host.AddScriptLPS(1);
@@ -2493,7 +2514,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2493 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2514 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2494 return; 2515 return;
2495 2516
2496 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
2497 module.MoveToTarget(npcId, World, pos, false, true, false); 2517 module.MoveToTarget(npcId, World, pos, false, true, false);
2498 } 2518 }
2499 } 2519 }
@@ -2513,11 +2533,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2513 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2533 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2514 return; 2534 return;
2515 2535
2516 Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
2517 module.MoveToTarget( 2536 module.MoveToTarget(
2518 new UUID(npc.m_string), 2537 new UUID(npc.m_string),
2519 World, 2538 World,
2520 pos, 2539 target,
2521 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, 2540 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2522 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, 2541 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2523 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); 2542 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
@@ -2569,7 +2588,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2569 ScenePresence sp = World.GetScenePresence(npcId); 2588 ScenePresence sp = World.GetScenePresence(npcId);
2570 2589
2571 if (sp != null) 2590 if (sp != null)
2572 sp.Rotation = LSL_Api.Rot2Quaternion(rotation); 2591 sp.Rotation = rotation;
2573 } 2592 }
2574 } 2593 }
2575 2594
@@ -2929,7 +2948,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2929 avatar.SpeedModifier = (float)SpeedModifier; 2948 avatar.SpeedModifier = (float)SpeedModifier;
2930 } 2949 }
2931 2950
2932 public void osKickAvatar(string FirstName,string SurName,string alert) 2951 public void osKickAvatar(string FirstName, string SurName, string alert)
2933 { 2952 {
2934 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 2953 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
2935 m_host.AddScriptLPS(1); 2954 m_host.AddScriptLPS(1);
@@ -2943,10 +2962,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2943 sp.ControllingClient.Kick(alert); 2962 sp.ControllingClient.Kick(alert);
2944 2963
2945 // ...and close on our side 2964 // ...and close on our side
2946 sp.Scene.IncomingCloseAgent(sp.UUID); 2965 sp.Scene.IncomingCloseAgent(sp.UUID, false);
2947 } 2966 }
2948 }); 2967 });
2949 } 2968 }
2969
2970 public LSL_Float osGetHealth(string avatar)
2971 {
2972 CheckThreatLevel(ThreatLevel.None, "osGetHealth");
2973 m_host.AddScriptLPS(1);
2974
2975 LSL_Float health = new LSL_Float(-1);
2976 ScenePresence presence = World.GetScenePresence(new UUID(avatar));
2977 if (presence != null) health = presence.Health;
2978 return health;
2979 }
2950 2980
2951 public void osCauseDamage(string avatar, double damage) 2981 public void osCauseDamage(string avatar, double damage)
2952 { 2982 {
@@ -2959,7 +2989,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2959 ScenePresence presence = World.GetScenePresence(avatarId); 2989 ScenePresence presence = World.GetScenePresence(avatarId);
2960 if (presence != null) 2990 if (presence != null)
2961 { 2991 {
2962 LandData land = World.GetLandData((float)pos.X, (float)pos.Y); 2992 LandData land = World.GetLandData(pos);
2963 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) 2993 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
2964 { 2994 {
2965 float health = presence.Health; 2995 float health = presence.Health;
@@ -3006,7 +3036,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3006 m_host.AddScriptLPS(1); 3036 m_host.AddScriptLPS(1);
3007 InitLSL(); 3037 InitLSL();
3008 3038
3009 return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); 3039 return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
3010 } 3040 }
3011 3041
3012 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) 3042 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
@@ -3015,7 +3045,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3015 m_host.AddScriptLPS(1); 3045 m_host.AddScriptLPS(1);
3016 InitLSL(); 3046 InitLSL();
3017 3047
3018 m_LSL_Api.SetPrimitiveParamsEx(prim, rules); 3048 m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
3019 } 3049 }
3020 3050
3021 /// <summary> 3051 /// <summary>
@@ -3247,6 +3277,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3247 } 3277 }
3248 } 3278 }
3249 3279
3280 #region Attachment commands
3281
3250 public void osForceAttachToAvatar(int attachmentPoint) 3282 public void osForceAttachToAvatar(int attachmentPoint)
3251 { 3283 {
3252 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); 3284 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@@ -3336,6 +3368,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3336 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3368 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3337 } 3369 }
3338 3370
3371 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
3372 {
3373 CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
3374
3375 m_host.AddScriptLPS(1);
3376
3377 UUID targetUUID;
3378 ScenePresence target;
3379 LSL_List resp = new LSL_List();
3380
3381 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3382 {
3383 foreach (object point in attachmentPoints.Data)
3384 {
3385 LSL_Integer ipoint = new LSL_Integer(
3386 (point is LSL_Integer || point is int || point is uint) ?
3387 (int)point :
3388 0
3389 );
3390 resp.Add(ipoint);
3391 if (ipoint == 0)
3392 {
3393 // indicates zero attachments
3394 resp.Add(new LSL_Integer(0));
3395 }
3396 else
3397 {
3398 // gets the number of attachments on the attachment point
3399 resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
3400 }
3401 }
3402 }
3403
3404 return resp;
3405 }
3406
3407 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
3408 {
3409 CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
3410 m_host.AddScriptLPS(1);
3411
3412 UUID targetUUID;
3413 ScenePresence target;
3414
3415 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3416 {
3417 List<int> aps = new List<int>();
3418 foreach (object point in attachmentPoints.Data)
3419 {
3420 int ipoint;
3421 if (int.TryParse(point.ToString(), out ipoint))
3422 {
3423 aps.Add(ipoint);
3424 }
3425 }
3426
3427 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3428
3429 bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
3430 bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
3431
3432 if (msgAll && invertPoints)
3433 {
3434 return;
3435 }
3436 else if (msgAll || invertPoints)
3437 {
3438 attachments = target.GetAttachments();
3439 }
3440 else
3441 {
3442 foreach (int point in aps)
3443 {
3444 if (point > 0)
3445 {
3446 attachments.AddRange(target.GetAttachments((uint)point));
3447 }
3448 }
3449 }
3450
3451 // if we have no attachments at this point, exit now
3452 if (attachments.Count == 0)
3453 {
3454 return;
3455 }
3456
3457 List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
3458
3459 if (invertPoints)
3460 {
3461 foreach (SceneObjectGroup attachment in attachments)
3462 {
3463 if (aps.Contains((int)attachment.AttachmentPoint))
3464 {
3465 ignoreThese.Add(attachment);
3466 }
3467 }
3468 }
3469
3470 foreach (SceneObjectGroup attachment in ignoreThese)
3471 {
3472 attachments.Remove(attachment);
3473 }
3474 ignoreThese.Clear();
3475
3476 // if inverting removed all attachments to check, exit now
3477 if (attachments.Count < 1)
3478 {
3479 return;
3480 }
3481
3482 if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
3483 {
3484 foreach (SceneObjectGroup attachment in attachments)
3485 {
3486 if (attachment.RootPart.CreatorID != m_host.CreatorID)
3487 {
3488 ignoreThese.Add(attachment);
3489 }
3490 }
3491
3492 foreach (SceneObjectGroup attachment in ignoreThese)
3493 {
3494 attachments.Remove(attachment);
3495 }
3496 ignoreThese.Clear();
3497
3498 // if filtering by same object creator removed all
3499 // attachments to check, exit now
3500 if (attachments.Count == 0)
3501 {
3502 return;
3503 }
3504 }
3505
3506 if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
3507 {
3508 foreach (SceneObjectGroup attachment in attachments)
3509 {
3510 if (attachment.RootPart.CreatorID != m_item.CreatorID)
3511 {
3512 ignoreThese.Add(attachment);
3513 }
3514 }
3515
3516 foreach (SceneObjectGroup attachment in ignoreThese)
3517 {
3518 attachments.Remove(attachment);
3519 }
3520 ignoreThese.Clear();
3521
3522 // if filtering by object creator must match originating
3523 // script creator removed all attachments to check,
3524 // exit now
3525 if (attachments.Count == 0)
3526 {
3527 return;
3528 }
3529 }
3530
3531 foreach (SceneObjectGroup attachment in attachments)
3532 {
3533 MessageObject(attachment.RootPart.UUID, message);
3534 }
3535 }
3536 }
3537
3538 #endregion
3539
3339 /// <summary> 3540 /// <summary>
3340 /// Checks if thing is a UUID. 3541 /// Checks if thing is a UUID.
3341 /// </summary> 3542 /// </summary>
@@ -3385,5 +3586,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3385 3586
3386 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); 3587 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
3387 } 3588 }
3589
3590 /// <summary>
3591 /// Sets the response type for an HTTP request/response
3592 /// </summary>
3593 /// <returns></returns>
3594 public void osSetContentType(LSL_Key id, string type)
3595 {
3596 CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
3597 if (m_UrlModule != null)
3598 m_UrlModule.HttpContentType(new UUID(id),type);
3599 }
3388 } 3600 }
3389} 3601}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 678f9d5..4dd795d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
352 q = avatar.Rotation; 352 q = avatar.Rotation;
353 } 353 }
354 354
355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
358 358
@@ -429,9 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
429 try 429 try
430 { 430 {
431 Vector3 diff = toRegionPos - fromRegionPos; 431 Vector3 diff = toRegionPos - fromRegionPos;
432 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 432 double dot = LSL_Types.Vector3.Dot(forward_dir, diff);
433 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 433 double mag_obj = LSL_Types.Vector3.Mag(diff);
434 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
435 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 434 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
436 } 435 }
437 catch 436 catch
@@ -483,7 +482,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
483 q = avatar.Rotation; 482 q = avatar.Rotation;
484 } 483 }
485 484
486 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 485 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
487 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 486 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
488 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 487 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
489 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); 488 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
@@ -564,8 +563,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
564 double ang_obj = 0; 563 double ang_obj = 0;
565 try 564 try
566 { 565 {
567 Vector3 diff = toRegionPos - fromRegionPos; 566 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(
568 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 567 toRegionPos - fromRegionPos);
569 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 568 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
570 double mag_obj = LSL_Types.Vector3.Mag(obj_dir); 569 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
571 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 570 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index af35258..05c20f9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -429,8 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
429 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); 429 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
430 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); 430 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
431 431
432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
433 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
434 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 433 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
434 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
435 } 435 }
436} 436}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 8c34ed3..0ea363a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
40 40
41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces 41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
42{ 42{
43 /// <summary>
44 /// To permit region owners to enable the extended scripting functionality
45 /// of OSSL, without allowing malicious scripts to access potentially
46 /// troublesome functions, each OSSL function is assigned a threat level,
47 /// and access to the functions is granted or denied based on a default
48 /// threshold set in OpenSim.ini (which can be overridden for individual
49 /// functions on a case-by-case basis)
50 /// </summary>
43 public enum ThreatLevel 51 public enum ThreatLevel
44 { 52 {
53 // Not documented, presumably means permanently disabled ?
45 NoAccess = -1, 54 NoAccess = -1,
55
56 /// <summary>
57 /// Function is no threat at all. It doesn't constitute a threat to
58 /// either users or the system and has no known side effects.
59 /// </summary>
46 None = 0, 60 None = 0,
61
62 /// <summary>
63 /// Abuse of this command can cause a nuisance to the region operator,
64 /// such as log message spew.
65 /// </summary>
47 Nuisance = 1, 66 Nuisance = 1,
67
68 /// <summary>
69 /// Extreme levels of abuse of this function can cause impaired
70 /// functioning of the region, or very gullible users can be tricked
71 /// into experiencing harmless effects.
72 /// </summary>
48 VeryLow = 2, 73 VeryLow = 2,
74
75 /// <summary>
76 /// Intentional abuse can cause crashes or malfunction under certain
77 /// circumstances, which can be easily rectified; or certain users can
78 /// be tricked into certain situations in an avoidable manner.
79 /// </summary>
49 Low = 3, 80 Low = 3,
81
82 /// <summary>
83 /// Intentional abuse can cause denial of service and crashes with
84 /// potential of data or state loss; or trusting users can be tricked
85 /// into embarrassing or uncomfortable situations.
86 /// </summary>
50 Moderate = 4, 87 Moderate = 4,
88
89 /// <summary>
90 /// Casual abuse can cause impaired functionality or temporary denial
91 /// of service conditions. Intentional abuse can easily cause crashes
92 /// with potential data loss, or can be used to trick experienced and
93 /// cautious users into unwanted situations, or changes global data
94 /// permanently and without undo ability.
95 /// </summary>
51 High = 5, 96 High = 5,
97
98 /// <summary>
99 /// Even normal use may, depending on the number of instances, or
100 /// frequency of use, result in severe service impairment or crash
101 /// with loss of data, or can be used to cause unwanted or harmful
102 /// effects on users without giving the user a means to avoid it.
103 /// </summary>
52 VeryHigh = 6, 104 VeryHigh = 6,
105
106 /// <summary>
107 /// Even casual use is a danger to region stability, or function allows
108 /// console or OS command execution, or function allows taking money
109 /// without consent, or allows deletion or modification of user data,
110 /// or allows the compromise of sensitive data by design.
111 /// </summary>
53 Severe = 7 112 Severe = 7
54 }; 113 };
55 114
@@ -98,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
98 void osAvatarPlayAnimation(string avatar, string animation); 157 void osAvatarPlayAnimation(string avatar, string animation);
99 void osAvatarStopAnimation(string avatar, string animation); 158 void osAvatarStopAnimation(string avatar, string animation);
100 159
101 // Attachment commands 160 #region Attachment commands
102 161
103 /// <summary> 162 /// <summary>
104 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH 163 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@@ -133,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
133 /// <remarks>Nothing happens if the object is not attached.</remarks> 192 /// <remarks>Nothing happens if the object is not attached.</remarks>
134 void osForceDetachFromAvatar(); 193 void osForceDetachFromAvatar();
135 194
195 /// <summary>
196 /// Returns a strided list of the specified attachment points and the number of attachments on those points.
197 /// </summary>
198 /// <param name="avatar">avatar UUID</param>
199 /// <param name="attachmentPoints">list of ATTACH_* constants</param>
200 /// <returns></returns>
201 LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
202
203 /// <summary>
204 /// Sends a specified message to the specified avatar's attachments on
205 /// the specified attachment points.
206 /// </summary>
207 /// <remarks>
208 /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
209 /// </remarks>
210 /// <param name="avatar">avatar UUID</param>
211 /// <param name="message">message string</param>
212 /// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
213 /// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
214 void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
215
216 #endregion
217
136 //texture draw functions 218 //texture draw functions
137 string osMovePen(string drawList, int x, int y); 219 string osMovePen(string drawList, int x, int y);
138 string osDrawLine(string drawList, int startX, int startY, int endX, int endY); 220 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
@@ -258,6 +340,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
258 int osGetSimulatorMemory(); 340 int osGetSimulatorMemory();
259 void osKickAvatar(string FirstName,string SurName,string alert); 341 void osKickAvatar(string FirstName,string SurName,string alert);
260 void osSetSpeed(string UUID, LSL_Float SpeedModifier); 342 void osSetSpeed(string UUID, LSL_Float SpeedModifier);
343 LSL_Float osGetHealth(string avatar);
261 void osCauseHealing(string avatar, double healing); 344 void osCauseHealing(string avatar, double healing);
262 void osCauseDamage(string avatar, double damage); 345 void osCauseDamage(string avatar, double damage);
263 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); 346 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -305,5 +388,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
305 /// </summary> 388 /// </summary>
306 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> 389 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
307 LSL_Key osGetRezzingObject(); 390 LSL_Key osGetRezzingObject();
391
392 /// <summary>
393 /// Sets the response type for an HTTP request/response
394 /// </summary>
395 /// <returns></returns>
396 void osSetContentType(LSL_Key id, string type);
308 } 397 }
309} 398}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index f989cc6..c788407 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
237 public const int ATTACH_HUD_BOTTOM = 37; 237 public const int ATTACH_HUD_BOTTOM = 37;
238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38; 238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
239 239
240 #region osMessageAttachments constants
241
242 /// <summary>
243 /// Instructs osMessageAttachements to send the message to attachments
244 /// on every point.
245 /// </summary>
246 /// <remarks>
247 /// One might expect this to be named OS_ATTACH_ALL, but then one might
248 /// also expect functions designed to attach or detach or get
249 /// attachments to work with it too. Attaching a no-copy item to
250 /// many attachments could be dangerous.
251 /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
252 /// message from being sent.
253 /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
254 /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
255 /// sent- this is expected behaviour.
256 /// </remarks>
257 public const int OS_ATTACH_MSG_ALL = -65535;
258
259 /// <summary>
260 /// Instructs osMessageAttachements to invert how the attachment points
261 /// list should be treated (e.g. go from inclusive operation to
262 /// exclusive operation).
263 /// </summary>
264 /// <remarks>
265 /// This might be used if you want to deliver a message to one set of
266 /// attachments and a different message to everything else. With
267 /// this flag, you only need to build one explicit list for both calls.
268 /// </remarks>
269 public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
270
271 /// <summary>
272 /// Instructs osMessageAttachments to only send the message to
273 /// attachments with a CreatorID that matches the host object CreatorID
274 /// </summary>
275 /// <remarks>
276 /// This would be used if distributed in an object vendor/updater server.
277 /// </remarks>
278 public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
279
280 /// <summary>
281 /// Instructs osMessageAttachments to only send the message to
282 /// attachments with a CreatorID that matches the sending script CreatorID
283 /// </summary>
284 /// <remarks>
285 /// This might be used if the script is distributed independently of a
286 /// containing object.
287 /// </remarks>
288 public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
289
290 #endregion
291
240 public const int LAND_LEVEL = 0; 292 public const int LAND_LEVEL = 0;
241 public const int LAND_RAISE = 1; 293 public const int LAND_RAISE = 1;
242 public const int LAND_LOWER = 2; 294 public const int LAND_LOWER = 2;
@@ -329,6 +381,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
329 public const int PRIM_OMEGA = 32; 381 public const int PRIM_OMEGA = 32;
330 public const int PRIM_POS_LOCAL = 33; 382 public const int PRIM_POS_LOCAL = 33;
331 public const int PRIM_LINK_TARGET = 34; 383 public const int PRIM_LINK_TARGET = 34;
384 public const int PRIM_SLICE = 35;
332 public const int PRIM_TEXGEN_DEFAULT = 0; 385 public const int PRIM_TEXGEN_DEFAULT = 0;
333 public const int PRIM_TEXGEN_PLANAR = 1; 386 public const int PRIM_TEXGEN_PLANAR = 1;
334 387
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 94405d2..52ca3da 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); 289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
290 } 290 }
291 291
292 // Avatar functions 292 #region Attachment commands
293 293
294 public void osForceAttachToAvatar(int attachmentPoint) 294 public void osForceAttachToAvatar(int attachmentPoint)
295 { 295 {
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
311 m_OSSL_Functions.osForceDetachFromAvatar(); 311 m_OSSL_Functions.osForceDetachFromAvatar();
312 } 312 }
313 313
314 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
315 {
316 return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
317 }
318
319 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
320 {
321 m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
322 }
323
324 #endregion
325
314 // Texture Draw functions 326 // Texture Draw functions
315 327
316 public string osMovePen(string drawList, int x, int y) 328 public string osMovePen(string drawList, int x, int y)
@@ -865,7 +877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
865 { 877 {
866 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); 878 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
867 } 879 }
868 880
881 public LSL_Float osGetHealth(string avatar)
882 {
883 return m_OSSL_Functions.osGetHealth(avatar);
884 }
885
869 public void osCauseDamage(string avatar, double damage) 886 public void osCauseDamage(string avatar, double damage)
870 { 887 {
871 m_OSSL_Functions.osCauseDamage(avatar, damage); 888 m_OSSL_Functions.osCauseDamage(avatar, damage);
@@ -950,5 +967,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
950 { 967 {
951 return m_OSSL_Functions.osGetRezzingObject(); 968 return m_OSSL_Functions.osGetRezzingObject();
952 } 969 }
970
971 public void osSetContentType(LSL_Key id, string type)
972 {
973 m_OSSL_Functions.osSetContentType(id,type);
974 }
953 } 975 }
954} 976}
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 17a0d69..03be2ab 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
546 "OpenSim.Region.ScriptEngine.Shared.dll")); 546 "OpenSim.Region.ScriptEngine.Shared.dll"));
547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); 548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
549 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
550 "OpenMetaverseTypes.dll"));
549 551
550 if (lang == enumCompileType.yp) 552 if (lang == enumCompileType.yp)
551 { 553 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 9e5fb24..22804f5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
164 else 164 else
165 { 165 {
166 // Set the values from the touch data provided by the client 166 // Set the values from the touch data provided by the client
167 touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); 167 touchST = new LSL_Types.Vector3(value.STCoord);
168 touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); 168 touchUV = new LSL_Types.Vector3(value.UVCoord);
169 touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); 169 touchNormal = new LSL_Types.Vector3(value.Normal);
170 touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); 170 touchBinormal = new LSL_Types.Vector3(value.Binormal);
171 touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); 171 touchPos = new LSL_Types.Vector3(value.Position);
172 touchFace = value.FaceIndex; 172 touchFace = value.FaceIndex;
173 } 173 }
174 } 174 }
@@ -189,19 +189,13 @@ namespace OpenSim.Region.ScriptEngine.Shared
189 Country = account.UserCountry; 189 Country = account.UserCountry;
190 190
191 Owner = Key; 191 Owner = Key;
192 Position = new LSL_Types.Vector3( 192 Position = new LSL_Types.Vector3(presence.AbsolutePosition);
193 presence.AbsolutePosition.X,
194 presence.AbsolutePosition.Y,
195 presence.AbsolutePosition.Z);
196 Rotation = new LSL_Types.Quaternion( 193 Rotation = new LSL_Types.Quaternion(
197 presence.Rotation.X, 194 presence.Rotation.X,
198 presence.Rotation.Y, 195 presence.Rotation.Y,
199 presence.Rotation.Z, 196 presence.Rotation.Z,
200 presence.Rotation.W); 197 presence.Rotation.W);
201 Velocity = new LSL_Types.Vector3( 198 Velocity = new LSL_Types.Vector3(presence.Velocity);
202 presence.Velocity.X,
203 presence.Velocity.Y,
204 presence.Velocity.Z);
205 199
206 Type = 0x01; // Avatar 200 Type = 0x01; // Avatar
207 if (presence.PresenceType == PresenceType.Npc) 201 if (presence.PresenceType == PresenceType.Npc)
@@ -254,16 +248,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
254 } 248 }
255 } 249 }
256 250
257 Position = new LSL_Types.Vector3(part.AbsolutePosition.X, 251 Position = new LSL_Types.Vector3(part.AbsolutePosition);
258 part.AbsolutePosition.Y,
259 part.AbsolutePosition.Z);
260 252
261 Quaternion wr = part.ParentGroup.GroupRotation; 253 Quaternion wr = part.ParentGroup.GroupRotation;
262 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); 254 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
263 255
264 Velocity = new LSL_Types.Vector3(part.Velocity.X, 256 Velocity = new LSL_Types.Vector3(part.Velocity);
265 part.Velocity.Y,
266 part.Velocity.Z);
267 } 257 }
268 } 258 }
269 259
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 8adf4c5..c9c4753 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -31,6 +31,11 @@ using System.Globalization;
31using System.Text.RegularExpressions; 31using System.Text.RegularExpressions;
32using OpenSim.Framework; 32using OpenSim.Framework;
33 33
34using OpenMetaverse;
35using OMV_Vector3 = OpenMetaverse.Vector3;
36using OMV_Vector3d = OpenMetaverse.Vector3d;
37using OMV_Quaternion = OpenMetaverse.Quaternion;
38
34namespace OpenSim.Region.ScriptEngine.Shared 39namespace OpenSim.Region.ScriptEngine.Shared
35{ 40{
36 [Serializable] 41 [Serializable]
@@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared
54 z = (float)vector.z; 59 z = (float)vector.z;
55 } 60 }
56 61
62 public Vector3(OMV_Vector3 vector)
63 {
64 x = vector.X;
65 y = vector.Y;
66 z = vector.Z;
67 }
68
69 public Vector3(OMV_Vector3d vector)
70 {
71 x = vector.X;
72 y = vector.Y;
73 z = vector.Z;
74 }
75
57 public Vector3(double X, double Y, double Z) 76 public Vector3(double X, double Y, double Z)
58 { 77 {
59 x = X; 78 x = X;
@@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared
109 return new list(new object[] { vec }); 128 return new list(new object[] { vec });
110 } 129 }
111 130
131 public static implicit operator OMV_Vector3(Vector3 vec)
132 {
133 return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z);
134 }
135
136 public static implicit operator Vector3(OMV_Vector3 vec)
137 {
138 return new Vector3(vec);
139 }
140
141 public static implicit operator OMV_Vector3d(Vector3 vec)
142 {
143 return new OMV_Vector3d(vec.x, vec.y, vec.z);
144 }
145
146 public static implicit operator Vector3(OMV_Vector3d vec)
147 {
148 return new Vector3(vec);
149 }
150
112 public static bool operator ==(Vector3 lhs, Vector3 rhs) 151 public static bool operator ==(Vector3 lhs, Vector3 rhs)
113 { 152 {
114 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 153 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
322 s = 1; 361 s = 1;
323 } 362 }
324 363
364 public Quaternion(OMV_Quaternion rot)
365 {
366 x = rot.X;
367 y = rot.Y;
368 z = rot.Z;
369 s = rot.W;
370 }
371
325 #endregion 372 #endregion
326 373
327 #region Overriders 374 #region Overriders
@@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared
368 return new list(new object[] { r }); 415 return new list(new object[] { r });
369 } 416 }
370 417
418 public static implicit operator OMV_Quaternion(Quaternion rot)
419 {
420 // LSL quaternions can normalize to 0, normal Quaternions can't.
421 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
422 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
423 OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
424 omvrot.Normalize();
425 return omvrot;
426 }
427
428 public static implicit operator Quaternion(OMV_Quaternion rot)
429 {
430 return new Quaternion(rot);
431 }
432
371 public static bool operator ==(Quaternion lhs, Quaternion rhs) 433 public static bool operator ==(Quaternion lhs, Quaternion rhs)
372 { 434 {
373 // Return true if the fields match: 435 // Return true if the fields match:
@@ -562,12 +624,23 @@ namespace OpenSim.Region.ScriptEngine.Shared
562 else if (m_data[itemIndex] is LSL_Types.LSLString) 624 else if (m_data[itemIndex] is LSL_Types.LSLString)
563 return new LSLInteger(m_data[itemIndex].ToString()); 625 return new LSLInteger(m_data[itemIndex].ToString());
564 else 626 else
565 throw new InvalidCastException(); 627 throw new InvalidCastException(string.Format(
628 "{0} expected but {1} given",
629 typeof(LSL_Types.LSLInteger).Name,
630 m_data[itemIndex] != null ?
631 m_data[itemIndex].GetType().Name : "null"));
566 } 632 }
567 633
568 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
569 { 635 {
570 return (LSL_Types.Vector3)m_data[itemIndex]; 636 if(m_data[itemIndex] is LSL_Types.Vector3)
637 return (LSL_Types.Vector3)m_data[itemIndex];
638 else
639 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null"));
571 } 644 }
572 645
573 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 5c4174e..cee10df 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -152,9 +152,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
152 det[0] = new DetectParams(); 152 det[0] = new DetectParams();
153 det[0].Key = remoteClient.AgentId; 153 det[0].Key = remoteClient.AgentId;
154 det[0].Populate(myScriptEngine.World); 154 det[0].Populate(myScriptEngine.World);
155 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, 155 det[0].OffsetPos = offsetPos;
156 offsetPos.Y,
157 offsetPos.Z);
158 156
159 if (originalID == 0) 157 if (originalID == 0)
160 { 158 {
@@ -298,9 +296,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
298 foreach (DetectedObject detobj in col.Colliders) 296 foreach (DetectedObject detobj in col.Colliders)
299 { 297 {
300 DetectParams d = new DetectParams(); 298 DetectParams d = new DetectParams();
301 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 299 d.Position = detobj.posVector;
302 detobj.posVector.Y,
303 detobj.posVector.Z);
304 d.Populate(myScriptEngine.World); 300 d.Populate(myScriptEngine.World);
305 det.Add(d); 301 det.Add(d);
306 myScriptEngine.PostObjectEvent(localID, new EventParams( 302 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -318,9 +314,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
318 foreach (DetectedObject detobj in col.Colliders) 314 foreach (DetectedObject detobj in col.Colliders)
319 { 315 {
320 DetectParams d = new DetectParams(); 316 DetectParams d = new DetectParams();
321 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 317 d.Position = detobj.posVector;
322 detobj.posVector.Y,
323 detobj.posVector.Z);
324 d.Populate(myScriptEngine.World); 318 d.Populate(myScriptEngine.World);
325 det.Add(d); 319 det.Add(d);
326 myScriptEngine.PostObjectEvent(localID, new EventParams( 320 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -337,9 +331,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
337 foreach (DetectedObject detobj in col.Colliders) 331 foreach (DetectedObject detobj in col.Colliders)
338 { 332 {
339 DetectParams d = new DetectParams(); 333 DetectParams d = new DetectParams();
340 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 334 d.Position = detobj.posVector;
341 detobj.posVector.Y,
342 detobj.posVector.Z);
343 d.Populate(myScriptEngine.World); 335 d.Populate(myScriptEngine.World);
344 det.Add(d); 336 det.Add(d);
345 myScriptEngine.PostObjectEvent(localID, new EventParams( 337 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -381,8 +373,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
381 myScriptEngine.PostObjectEvent(localID, new EventParams( 373 myScriptEngine.PostObjectEvent(localID, new EventParams(
382 "at_target", new object[] { 374 "at_target", new object[] {
383 new LSL_Types.LSLInteger(handle), 375 new LSL_Types.LSLInteger(handle),
384 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), 376 new LSL_Types.Vector3(targetpos),
385 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, 377 new LSL_Types.Vector3(atpos) },
386 new DetectParams[0])); 378 new DetectParams[0]));
387 } 379 }
388 380
@@ -399,8 +391,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
399 myScriptEngine.PostObjectEvent(localID, new EventParams( 391 myScriptEngine.PostObjectEvent(localID, new EventParams(
400 "at_rot_target", new object[] { 392 "at_rot_target", new object[] {
401 new LSL_Types.LSLInteger(handle), 393 new LSL_Types.LSLInteger(handle),
402 new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), 394 new LSL_Types.Quaternion(targetrot),
403 new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, 395 new LSL_Types.Quaternion(atrot) },
404 new DetectParams[0])); 396 new DetectParams[0]));
405 } 397 }
406 398
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f6cb7df..9f05666 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -656,7 +656,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
656 if (m_Assemblies.ContainsKey(instance.AssetID)) 656 if (m_Assemblies.ContainsKey(instance.AssetID))
657 { 657 {
658 string assembly = m_Assemblies[instance.AssetID]; 658 string assembly = m_Assemblies[instance.AssetID];
659 instance.SaveState(assembly); 659
660 try
661 {
662 instance.SaveState(assembly);
663 }
664 catch (Exception e)
665 {
666 m_log.Error(
667 string.Format(
668 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
669 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
670 , e);
671 }
660 } 672 }
661 673
662 // Clear the event queue and abort the instance thread 674 // Clear the event queue and abort the instance thread
@@ -778,7 +790,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
778 assembly = m_Assemblies[i.AssetID]; 790 assembly = m_Assemblies[i.AssetID];
779 791
780 792
781 i.SaveState(assembly); 793 try
794 {
795 i.SaveState(assembly);
796 }
797 catch (Exception e)
798 {
799 m_log.Error(
800 string.Format(
801 "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
802 i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name)
803 , e);
804 }
782 } 805 }
783 806
784 instances.Clear(); 807 instances.Clear();
@@ -971,6 +994,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
971 // This delay exists to stop mono problems where script compilation and startup would stop the sim 994 // This delay exists to stop mono problems where script compilation and startup would stop the sim
972 // working properly for the session. 995 // working properly for the session.
973 System.Threading.Thread.Sleep(m_StartDelay); 996 System.Threading.Thread.Sleep(m_StartDelay);
997
998 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
974 } 999 }
975 1000
976 object[] o; 1001 object[] o;
@@ -986,13 +1011,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
986 if (m_InitialStartup) 1011 if (m_InitialStartup)
987 if (scriptsStarted % 50 == 0) 1012 if (scriptsStarted % 50 == 0)
988 m_log.InfoFormat( 1013 m_log.InfoFormat(
989 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1014 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
990 } 1015 }
991 } 1016 }
992 1017
993 if (m_InitialStartup) 1018 if (m_InitialStartup)
994 m_log.InfoFormat( 1019 m_log.InfoFormat(
995 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1020 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
996 1021
997 // NOTE: Despite having a lockless queue, this lock is required 1022 // NOTE: Despite having a lockless queue, this lock is required
998 // to make sure there is never no compile thread while there 1023 // to make sure there is never no compile thread while there
@@ -1053,10 +1078,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1053 return false; 1078 return false;
1054 } 1079 }
1055 1080
1056 UUID assetID = item.AssetID; 1081 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1057 1085
1058 //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", 1086 UUID assetID = item.AssetID;
1059 // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
1060 1087
1061 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); 1088 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
1062 1089
@@ -1235,10 +1262,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1235 item.Name, startParam, postOnRez, 1262 item.Name, startParam, postOnRez,
1236 stateSource, m_MaxScriptQueue); 1263 stateSource, m_MaxScriptQueue);
1237 1264
1238 m_log.DebugFormat( 1265// m_log.DebugFormat(
1239 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1240 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1241 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1268// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1242 1269
1243 if (presence != null) 1270 if (presence != null)
1244 { 1271 {
@@ -1554,9 +1581,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1554 else if (p[i] is string) 1581 else if (p[i] is string)
1555 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1582 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1556 else if (p[i] is Vector3) 1583 else if (p[i] is Vector3)
1557 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1584 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1558 else if (p[i] is Quaternion) 1585 else if (p[i] is Quaternion)
1559 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1586 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1560 else if (p[i] is float) 1587 else if (p[i] is float)
1561 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1588 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1562 else 1589 else
@@ -1580,9 +1607,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1580 else if (p[i] is string) 1607 else if (p[i] is string)
1581 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1608 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1582 else if (p[i] is Vector3) 1609 else if (p[i] is Vector3)
1583 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1610 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1584 else if (p[i] is Quaternion) 1611 else if (p[i] is Quaternion)
1585 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1612 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1586 else if (p[i] is float) 1613 else if (p[i] is float)
1587 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1614 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1588 else 1615 else
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b137c05..0cff6ed 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.IO; 30using System.IO;
30using System.Reflection; 31using System.Reflection;
31using System.Threading; 32using System.Threading;
@@ -71,10 +72,17 @@ namespace OpenSim.Server.Base
71 // 72 //
72 private string m_pidFile = String.Empty; 73 private string m_pidFile = String.Empty;
73 74
75 /// <summary>
76 /// Time at which this server was started
77 /// </summary>
78 protected DateTime m_startuptime;
79
74 // Handle all the automagical stuff 80 // Handle all the automagical stuff
75 // 81 //
76 public ServicesServerBase(string prompt, string[] args) 82 public ServicesServerBase(string prompt, string[] args)
77 { 83 {
84 m_startuptime = DateTime.Now;
85
78 // Save raw arguments 86 // Save raw arguments
79 // 87 //
80 m_Arguments = args; 88 m_Arguments = args;
@@ -250,6 +258,10 @@ namespace OpenSim.Server.Base
250 "command-script <script>", 258 "command-script <script>",
251 "Run a command script from file", HandleScript); 259 "Run a command script from file", HandleScript);
252 260
261 MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
262 "show uptime",
263 "Show server uptime", HandleShow);
264
253 265
254 // Allow derived classes to perform initialization that 266 // Allow derived classes to perform initialization that
255 // needs to be done after the console has opened 267 // needs to be done after the console has opened
@@ -345,5 +357,34 @@ namespace OpenSim.Server.Base
345 { 357 {
346 } 358 }
347 } 359 }
360
361 public virtual void HandleShow(string module, string[] cmd)
362 {
363 List<string> args = new List<string>(cmd);
364
365 args.RemoveAt(0);
366
367 string[] showParams = args.ToArray();
368
369 switch (showParams[0])
370 {
371 case "uptime":
372 MainConsole.Instance.Output(GetUptimeReport());
373 break;
374 }
375 }
376
377 /// <summary>
378 /// Return a report about the uptime of this server
379 /// </summary>
380 /// <returns></returns>
381 protected string GetUptimeReport()
382 {
383 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
384 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
385 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
386
387 return sb.ToString();
388 }
348 } 389 }
349} 390}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 0e4d794..67a10b0 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking"); 112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113 113
114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); 114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); 115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
116 116
117 OSDMap extraData = new OSDMap 117 OSDMap extraData = new OSDMap
118 { 118 {
@@ -297,7 +297,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
297 List<GridRegion> foundRegions = new List<GridRegion>(); 297 List<GridRegion> foundRegions = new List<GridRegion>();
298 298
299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0); 299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
300 Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0); 300 Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
301 301
302 NameValueCollection requestArgs = new NameValueCollection 302 NameValueCollection requestArgs = new NameValueCollection
303 { 303 {
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index aab403a..5bdea06 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -137,9 +137,14 @@ namespace OpenSim.Services.GridService
137 if (regionInfos.RegionID == UUID.Zero) 137 if (regionInfos.RegionID == UUID.Zero)
138 return "Invalid RegionID - cannot be zero UUID"; 138 return "Invalid RegionID - cannot be zero UUID";
139 139
140 // This needs better sanity testing. What if regionInfo is registering in
141 // overlapping coords?
142 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 140 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
141 if ((region != null) && (region.RegionID != regionInfos.RegionID))
142 {
143 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
144 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
145 return "Region overlaps another region";
146 }
147
143 if (region != null) 148 if (region != null)
144 { 149 {
145 // There is a preexisting record 150 // There is a preexisting record
@@ -176,19 +181,36 @@ namespace OpenSim.Services.GridService
176 } 181 }
177 } 182 }
178 183
179 if ((region != null) && (region.RegionID != regionInfos.RegionID)) 184 // If we get here, the destination is clear. Now for the real check.
185
186 if (!m_AllowDuplicateNames)
180 { 187 {
181 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", 188 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
182 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 189 if (dupe != null && dupe.Count > 0)
183 return "Region overlaps another region"; 190 {
191 foreach (RegionData d in dupe)
192 {
193 if (d.RegionID != regionInfos.RegionID)
194 {
195 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
196 regionInfos.RegionName, regionInfos.RegionID);
197 return "Duplicate region name";
198 }
199 }
200 }
184 } 201 }
185 202
203 // If there is an old record for us, delete it if it is elsewhere.
204 region = m_Database.Get(regionInfos.RegionID, scopeID);
186 if ((region != null) && (region.RegionID == regionInfos.RegionID) && 205 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
187 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) 206 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
188 { 207 {
189 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0) 208 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
190 return "Can't move this region"; 209 return "Can't move this region";
191 210
211 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
212 return "Region locked out";
213
192 // Region reregistering in other coordinates. Delete the old entry 214 // Region reregistering in other coordinates. Delete the old entry
193 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.", 215 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
194 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 216 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
@@ -203,23 +225,6 @@ namespace OpenSim.Services.GridService
203 } 225 }
204 } 226 }
205 227
206 if (!m_AllowDuplicateNames)
207 {
208 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
209 if (dupe != null && dupe.Count > 0)
210 {
211 foreach (RegionData d in dupe)
212 {
213 if (d.RegionID != regionInfos.RegionID)
214 {
215 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
216 regionInfos.RegionName, regionInfos.RegionID);
217 return "Duplicate region name";
218 }
219 }
220 }
221 }
222
223 // Everything is ok, let's register 228 // Everything is ok, let's register
224 RegionData rdata = RegionInfo2RegionData(regionInfos); 229 RegionData rdata = RegionInfo2RegionData(regionInfos);
225 rdata.ScopeID = scopeID; 230 rdata.ScopeID = scopeID;
@@ -227,8 +232,6 @@ namespace OpenSim.Services.GridService
227 if (region != null) 232 if (region != null)
228 { 233 {
229 int oldFlags = Convert.ToInt32(region.Data["flags"]); 234 int oldFlags = Convert.ToInt32(region.Data["flags"]);
230 if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
231 return "Region locked out";
232 235
233 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation; 236 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
234 237
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 7518b86..309dab4 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
94 94
95 m_Database = LoadPlugin<IXInventoryData>(dllName, 95 m_Database = LoadPlugin<IXInventoryData>(dllName,
96 new Object[] {connString, String.Empty}); 96 new Object[] {connString, String.Empty});
97
97 if (m_Database == null) 98 if (m_Database == null)
98 throw new Exception("Could not find a storage interface in the given module"); 99 throw new Exception("Could not find a storage interface in the given module");
99 } 100 }
@@ -229,10 +230,28 @@ namespace OpenSim.Services.InventoryService
229 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 230 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
230 { 231 {
231// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 232// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
233
234 InventoryFolderBase rootFolder = GetRootFolder(principalID);
235
236 if (rootFolder == null)
237 {
238 m_log.WarnFormat(
239 "[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
240 principalID, type);
241
242 return null;
243 }
244
245 return GetSystemFolderForType(rootFolder, type);
246 }
247
248 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
249 {
250// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
232 251
233 XInventoryFolder[] folders = m_Database.GetFolders( 252 XInventoryFolder[] folders = m_Database.GetFolders(
234 new string[] { "agentID", "type"}, 253 new string[] { "agentID", "parentFolderID", "type"},
235 new string[] { principalID.ToString(), ((int)type).ToString() }); 254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
236 255
237 if (folders.Length == 0) 256 if (folders.Length == 0)
238 { 257 {
@@ -308,22 +327,38 @@ namespace OpenSim.Services.InventoryService
308 if (check != null) 327 if (check != null)
309 return false; 328 return false;
310 329
311 if (folder.Type == (short)AssetType.Folder 330 if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
312 || folder.Type == (short)AssetType.Unknown
313 || folder.Type == (short)AssetType.OutfitFolder
314 || GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
315 { 331 {
316 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 332 InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
317 return m_Database.StoreFolder(xFolder); 333
318 } 334 if (rootFolder == null)
319 else 335 {
320 { 336 m_log.WarnFormat(
321 m_log.WarnFormat( 337 "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
322 "[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}", 338 folder.Owner, folder.Type);
323 folder.Type, folder.Name, folder.ParentID, folder.Owner); 339
340 return false;
341 }
342
343 // Check we're not trying to add this as a system folder.
344 if (folder.ParentID == rootFolder.ID)
345 {
346 InventoryFolderBase existingSystemFolder
347 = GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
348
349 if (existingSystemFolder != null)
350 {
351 m_log.WarnFormat(
352 "[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
353 folder.Type, folder.Name, folder.ParentID, folder.Owner);
354
355 return false;
356 }
357 }
324 } 358 }
325 359
326 return false; 360 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
361 return m_Database.StoreFolder(xFolder);
327 } 362 }
328 363
329 public virtual bool UpdateFolder(InventoryFolderBase folder) 364 public virtual bool UpdateFolder(InventoryFolderBase folder)
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 7598cc3..fc49169 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
245 config.AddConfig("Modules"); 245 config.AddConfig("Modules");
246 config.AddConfig("InventoryService"); 246 config.AddConfig("InventoryService");
247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); 247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); 248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); 249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
250 250
251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); 251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
index b3a7c9e..87d9410 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
200 200
201 InventoryFolderBase newFolder 201 InventoryFolderBase newFolder
202 = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); 202 = new InventoryFolderBase(
203 UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
204
203 inventoryService.AddFolder(newFolder); 205 inventoryService.AddFolder(newFolder);
204 206
205 if (components.Length > 1) 207 if (components.Length > 1)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 6add130..4e3bc67 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -935,12 +935,12 @@ namespace OpenSim.Tests.Common.Mock
935 Close(); 935 Close();
936 } 936 }
937 937
938 public void Close(bool c) 938 public void Close()
939 { 939 {
940 Close(); 940 Close(true, false);
941 } 941 }
942 942
943 public void Close() 943 public void Close(bool sendStop, bool force)
944 { 944 {
945 // Fire the callback for this connection closing 945 // Fire the callback for this connection closing
946 // This is necesary to get the presence detector to notice that a client has logged out. 946 // This is necesary to get the presence detector to notice that a client has logged out.
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
new file mode 100644
index 0000000..bca5979
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -0,0 +1,131 @@
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 log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Data;
36
37namespace OpenSim.Tests.Common.Mock
38{
39 public class TestXInventoryDataPlugin : IXInventoryData
40 {
41 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
42 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
43
44 public TestXInventoryDataPlugin(string conn, string realm) {}
45
46 public XInventoryItem[] GetItems(string[] fields, string[] vals)
47 {
48 List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
49
50 return origItems.Select(i => i.Clone()).ToArray();
51 }
52
53 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
54 {
55 List<XInventoryFolder> origFolders
56 = Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
57
58 return origFolders.Select(f => f.Clone()).ToArray();
59 }
60
61 private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
62 {
63 List<T> entities = inputEntities;
64
65 for (int i = 0; i < fields.Length; i++)
66 {
67 entities
68 = entities.Where(
69 e =>
70 {
71 FieldInfo fi = typeof(T).GetField(fields[i]);
72 if (fi == null)
73 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
74
75 return fi.GetValue(e).ToString() == vals[i];
76 }
77 ).ToList();
78 }
79
80 return entities;
81 }
82
83 public bool StoreFolder(XInventoryFolder folder)
84 {
85 m_allFolders[folder.folderID] = folder.Clone();
86
87// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
88
89 return true;
90 }
91
92 public bool StoreItem(XInventoryItem item)
93 {
94 m_allItems[item.inventoryID] = item.Clone();
95
96// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
97
98 return true;
99 }
100
101 public bool DeleteFolders(string field, string val)
102 {
103 return DeleteFolders(new string[] { field }, new string[] { val });
104 }
105
106 public bool DeleteFolders(string[] fields, string[] vals)
107 {
108 XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
109 Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
110
111 return true;
112 }
113
114 public bool DeleteItems(string field, string val)
115 {
116 return DeleteItems(new string[] { field }, new string[] { val });
117 }
118
119 public bool DeleteItems(string[] fields, string[] vals)
120 {
121 XInventoryItem[] itemsToDelete = GetItems(fields, vals);
122 Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
123
124 return true;
125 }
126
127 public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
128 public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
129 public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
130 }
131} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs
index 30121fe..57da802 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
95 public static void EnableLogging() 95 public static void EnableLogging()
96 { 96 {
97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); 97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
98 EnableLoggingConfigStream.Position = 0;
98 } 99 }
99 100
100 /// <summary> 101 /// <summary>
diff --git a/OpenSim/Tests/Torture/NPCTortureTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index 731df68..627765b 100644
--- a/OpenSim/Tests/Torture/NPCTortureTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
47using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
49 49
50namespace OpenSim.Tests.Torture 50namespace OpenSim.Tests.Performance
51{ 51{
52 /// <summary> 52 /// <summary>
53 /// NPC torture tests 53 /// NPC performance tests
54 /// </summary> 54 /// </summary>
55 /// <remarks> 55 /// <remarks>
56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Torture
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCTortureTests 61 public class NPCPerformanceTests
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Torture/ObjectTortureTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 195d47b..2264d86 100644
--- a/OpenSim/Tests/Torture/ObjectTortureTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
@@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common; 36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 37using OpenSim.Tests.Common.Mock;
38 38
39namespace OpenSim.Tests.Torture 39namespace OpenSim.Tests.Performance
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// Object torture tests 42 /// Object performance tests
43 /// </summary> 43 /// </summary>
44 /// <remarks> 44 /// <remarks>
45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Torture
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectTortureTests 50 public class ObjectPerformanceTests
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Torture/ScriptTortureTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index 24f278f..d708abd 100644
--- a/OpenSim/Tests/Torture/ScriptTortureTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
@@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
42using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
43using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
44 44
45namespace OpenSim.Tests.Torture 45namespace OpenSim.Tests.Performance
46{ 46{
47 /// <summary> 47 /// <summary>
48 /// Script torture tests 48 /// Script performance tests
49 /// </summary> 49 /// </summary>
50 /// <remarks> 50 /// <remarks>
51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Torture
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptTortureTests 56 public class ScriptPerformanceTests
57 { 57 {
58 private TestScene m_scene; 58 private TestScene m_scene;
59 private XEngine m_xEngine; 59 private XEngine m_xEngine;
diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
new file mode 100644
index 0000000..1f220c0
--- /dev/null
+++ b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
@@ -0,0 +1,132 @@
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.IO;
31using System.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenMetaverse.Assets;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
40using OpenSim.Region.CoreModules.Scripting.VectorRender;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Serialization;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Tests.Stress
47{
48 [TestFixture]
49 public class VectorRenderModuleStressTests : OpenSimTestCase
50 {
51 public Scene Scene { get; private set; }
52 public DynamicTextureModule Dtm { get; private set; }
53 public VectorRenderModule Vrm { get; private set; }
54
55 private void SetupScene(bool reuseTextures)
56 {
57 Scene = new SceneHelpers().SetupScene();
58
59 Dtm = new DynamicTextureModule();
60 Dtm.ReuseTextures = reuseTextures;
61
62 Vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
65 }
66
67 [Test]
68 public void TestConcurrentRepeatedDraw()
69 {
70 int threads = 4;
71 TestHelpers.InMethod();
72
73 SetupScene(false);
74
75 List<Drawer> drawers = new List<Drawer>();
76
77 for (int i = 0; i < threads; i++)
78 {
79 Drawer d = new Drawer(this, i);
80 drawers.Add(d);
81 Console.WriteLine("Starting drawer {0}", i);
82 Util.FireAndForget(o => d.Draw());
83 }
84
85 Thread.Sleep(10 * 60 * 1000);
86
87 drawers.ForEach(d => d.Ready = false);
88 drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
89 }
90
91 class Drawer
92 {
93 public int Number { get; private set; }
94 public int Pass { get; private set; }
95 public bool Ready { get; set; }
96
97 private VectorRenderModuleStressTests m_tests;
98
99 public Drawer(VectorRenderModuleStressTests tests, int number)
100 {
101 m_tests = tests;
102 Number = number;
103 Ready = true;
104 }
105
106 public void Draw()
107 {
108 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
109
110 while (Ready)
111 {
112 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
113
114 // Ensure unique text
115 string text = string.Format("{0:D2}{1}", Number, Pass);
116
117 m_tests.Dtm.AddDynamicTextureData(
118 m_tests.Scene.RegionInfo.RegionID,
119 so.UUID,
120 m_tests.Vrm.GetContentType(),
121 string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
122 "",
123 0);
124
125 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
126
127 Pass++;
128 }
129 }
130 }
131 }
132} \ No newline at end of file