From 14d05dc2a907fcb304e622ab85150049b43f4fd5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 11 Jul 2012 19:54:40 +0100 Subject: Add regression TestRezScriptedAttachmentsFromInventory() though this currently only checks for the presence of script items, not for started scripts --- .../Attachments/Tests/AttachmentsModuleTests.cs | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 3e06900..416aa6f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests } [Test] - public void TestAddAttachmentFromInventory() + public void TestRezAttachmentFromInventory() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -217,6 +217,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); } + /// + /// Test specific conditions associated with rezzing a scripted attachment from inventory. + /// + [Test] + public void TestRezScriptedAttachmentFromInventory() + { + TestHelpers.InMethod(); + + Scene scene = CreateDefaultTestScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); + ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); + TaskInventoryHelpers.AddScript(scene, so.RootPart); + InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); + + scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + + // TODO: Need to have a test that checks the script is actually started but this involves a lot more + // plumbing of the script engine and either pausing for events or more infrastructure to turn off various + // script engine delays/asychronicity that isn't helpful in an automated regression testing context. + SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); + Assert.That(attSo.ContainsScripts(), Is.True); + } + [Test] public void TestDetachAttachmentToGround() { -- cgit v1.1 From fc2456320646df66b95a06d4cd292c3b2385a8ea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 11 Jul 2012 21:43:35 +0100 Subject: Add regression TestDetachScriptedAttachmentToInventory() This currently only does a relatively crude check for a ScriptState node in the serialized xml --- .../Avatar/Attachments/AttachmentsModule.cs | 16 ++- .../Attachments/Tests/AttachmentsModuleTests.cs | 131 ++++++++++++++++++--- .../Framework/Interfaces/IAttachmentsModule.cs | 2 +- .../Framework/Scenes/SceneObjectPartInventory.cs | 4 + .../Api/Implementation/AsyncCommandManager.cs | 15 ++- .../Shared/Api/Implementation/Plugins/Listener.cs | 8 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 4 +- 7 files changed, 149 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index efab6ed..64ee7e4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -339,7 +339,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); } - public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) + public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) { if (!Enabled) return null; @@ -527,6 +527,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// + /// private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) { // Saving attachments for NPCs messes them up for the real owner! @@ -720,18 +721,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, sp.UUID, true); - // m_log.DebugFormat( - // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", - // objatt.Name, remoteClient.Name, AttachmentPt); - if (objatt != null) { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", +// objatt.Name, sp.Name, attachmentPt, m_scene.Name); + // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. objatt.HasGroupChanged = false; bool tainted = false; if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) tainted = true; + // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal + // course of events. If not, then it's probably not worth trying to recover the situation + // since this is more likely to trigger further exceptions and confuse later debugging. If + // exceptions can be thrown in expected error conditions (not NREs) then make this consistent + // since other normal error conditions will simply return false instead. // This will throw if the attachment fails try { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 416aa6f..81e889d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -31,6 +31,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Timers; +using System.Xml; using Timer=System.Timers.Timer; using Nini.Config; using NUnit.Framework; @@ -41,10 +42,12 @@ using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Framework; using OpenSim.Region.CoreModules.Framework.EntityTransfer; using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.Scripting.WorldComm; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ScriptEngine.XEngine; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -57,6 +60,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests [TestFixture] public class AttachmentsModuleTests : OpenSimTestCase { + private AutoResetEvent m_chatEvent = new AutoResetEvent(false); + private OSChatMessage m_osChatMessageReceived; + [TestFixtureSetUp] public void FixtureInit() { @@ -72,16 +78,73 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; } - private Scene CreateDefaultTestScene() + private void OnChatFromWorld(object sender, OSChatMessage oscm) + { +// Console.WriteLine("Got chat [{0}]", oscm.Message); + + m_osChatMessageReceived = oscm; + m_chatEvent.Set(); + } + + private Scene CreateTestScene() + { + IConfigSource config = new IniConfigSource(); + List modules = new List(); + + AddCommonConfig(config, modules); + + Scene scene + = new SceneHelpers().SetupScene( + "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); + SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); + + return scene; + } + + private Scene CreateScriptingEnabledTestScene() { IConfigSource config = new IniConfigSource(); + List modules = new List(); + + AddCommonConfig(config, modules); + AddScriptingConfig(config, modules); + + Scene scene + = new SceneHelpers().SetupScene( + "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); + SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); + + scene.StartScripts(); + + return scene; + } + + private void AddCommonConfig(IConfigSource config, List modules) + { config.AddConfig("Modules"); config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, config, new AttachmentsModule(), new BasicInventoryAccessModule()); + modules.Add(new AttachmentsModule()); + modules.Add(new BasicInventoryAccessModule()); + } - return scene; + private void AddScriptingConfig(IConfigSource config, List modules) + { + IConfig startupConfig = config.AddConfig("Startup"); + startupConfig.Set("DefaultScriptEngine", "XEngine"); + + IConfig xEngineConfig = config.AddConfig("XEngine"); + xEngineConfig.Set("Enabled", "true"); + + // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call + // to AssemblyResolver.OnAssemblyResolve fails. + xEngineConfig.Set("AppDomainLoading", "false"); + + modules.Add(new XEngine()); + + // Necessary to stop serialization complaining + // FIXME: Stop this being necessary if at all possible +// modules.Add(new WorldCommModule()); } /// @@ -116,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -163,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -190,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); @@ -225,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { TestHelpers.InMethod(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); @@ -248,7 +311,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); @@ -278,9 +341,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public void TestDetachAttachmentToInventory() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); @@ -303,6 +365,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests } /// + /// Test specific conditions associated with detaching a scripted attachment from inventory. + /// + [Test] + public void TestDetachScriptedAttachmentToInventory() + { + TestHelpers.InMethod(); + TestHelpers.EnableLogging(); + + Scene scene = CreateScriptingEnabledTestScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); + ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); + TaskInventoryHelpers.AddScript(scene, so.RootPart); + InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); + + // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. + // In the future, we need to be able to do this programatically more predicably. + scene.EventManager.OnChatFromWorld += OnChatFromWorld; + + SceneObjectGroup soRezzed + = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + + // Wait for chat to signal rezzed script has been started. + m_chatEvent.WaitOne(60000); + + scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed); + + InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); + AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); + + XmlDocument soXml = new XmlDocument(); + soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); + + XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); + Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); + } + + /// /// Test that attachments don't hang about in the scene when the agent is closed /// [Test] @@ -311,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); @@ -334,7 +435,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); @@ -370,7 +471,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { TestHelpers.InMethod(); - Scene scene = CreateDefaultTestScene(); + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index ba35a41..351e603 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// The scene object that was attached. Null if the scene object could not be found - ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); + SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); /// /// Rez multiple attachments from a user's inventory diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index cf2ed1a..821fd81 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1295,6 +1295,10 @@ namespace OpenSim.Region.Framework.Scenes { if (e != null) { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Getting script state from engine {0} for {1} in part {2} in group {3} in {4}", +// e.Name, item.Name, m_part.Name, m_part.ParentGroup.Name, m_part.ParentGroup.Scene.Name); + string n = e.GetXMLState(item.ItemID); if (n != String.Empty) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index 993d10f..5b22860 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -233,17 +233,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_Timer[engine].UnSetTimerEvents(localID, itemID); // Remove from: HttpRequest - IHttpRequestModule iHttpReq = - engine.World.RequestModuleInterface(); - iHttpReq.StopHttpRequest(localID, itemID); + IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface(); + if (iHttpReq != null) + iHttpReq.StopHttpRequest(localID, itemID); IWorldComm comms = engine.World.RequestModuleInterface(); if (comms != null) comms.DeleteListener(itemID); IXMLRPC xmlrpc = engine.World.RequestModuleInterface(); - xmlrpc.DeleteChannels(itemID); - xmlrpc.CancelSRDRequests(itemID); + if (xmlrpc != null) + { + xmlrpc.DeleteChannels(itemID); + xmlrpc.CancelSRDRequests(itemID); + } // Remove Sensors m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); @@ -305,7 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { List data = new List(); - Object[] listeners=m_Listener[engine].GetSerializationData(itemID); + Object[] listeners = m_Listener[engine].GetSerializationData(itemID); if (listeners.Length > 0) { data.Add("listener"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs index 93e0261..efa86fc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs @@ -88,13 +88,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins public Object[] GetSerializationData(UUID itemID) { - return m_commsPlugin.GetSerializationData(itemID); + if (m_commsPlugin != null) + return m_commsPlugin.GetSerializationData(itemID); + else + return new Object[]{}; } public void CreateFromData(uint localID, UUID itemID, UUID hostID, Object[] data) { - m_commsPlugin.CreateFromData(localID, itemID, hostID, data); + if (m_commsPlugin != null) + m_commsPlugin.CreateFromData(localID, itemID, hostID, data); } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index efcae94..e07ae1c 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1676,12 +1676,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine public string GetXMLState(UUID itemID) { -// m_log.DebugFormat("[XEngine]: Getting XML state for {0}", itemID); +// m_log.DebugFormat("[XEngine]: Getting XML state for script instance {0}", itemID); IScriptInstance instance = GetInstance(itemID); if (instance == null) { -// m_log.DebugFormat("[XEngine]: Found no script for {0}, returning empty string", itemID); +// m_log.DebugFormat("[XEngine]: Found no script instance for {0}, returning empty string", itemID); return ""; } -- cgit v1.1 From 0e611c47d322e1596d4636e283b9b855c7e58b60 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 11 Jul 2012 21:46:46 +0100 Subject: Remove WorldComm module from the regression TestCompileAndStartScript() since the infrastructure no longer fails if this module isn't present, at least on the tested codepaths --- OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index a3f848c..fe4b0fa 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -58,9 +58,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests // Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); m_xEngine = new XEngine(); - // Necessary to stop serialization complaining - WorldCommModule wcModule = new WorldCommModule(); - IniConfigSource configSource = new IniConfigSource(); IConfig startupConfig = configSource.AddConfig("Startup"); @@ -74,7 +71,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests xEngineConfig.Set("AppDomainLoading", "false"); m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); - SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine, wcModule); + SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); m_scene.StartScripts(); } -- cgit v1.1 From 33cff9b9d7c9d742b1cb7064ed78677e3f030e72 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 11 Jul 2012 21:55:18 +0100 Subject: Allow XEngine StartDelay to be configured in the [XEngine] config section. This is only currently meant for use by regression tests that don't have any issues if XEngine is started up quickly, since no other operations will be occuring simultaneously. Therefore, this is not yet documented externally. --- .../Avatar/Attachments/Tests/AttachmentsModuleTests.cs | 3 ++- OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs | 1 + OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 11 +++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 81e889d..b021a47 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -135,6 +135,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests IConfig xEngineConfig = config.AddConfig("XEngine"); xEngineConfig.Set("Enabled", "true"); + xEngineConfig.Set("StartDelay", "0"); // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call // to AssemblyResolver.OnAssemblyResolve fails. @@ -371,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public void TestDetachScriptedAttachmentToInventory() { TestHelpers.InMethod(); - TestHelpers.EnableLogging(); +// TestHelpers.EnableLogging(); Scene scene = CreateScriptingEnabledTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index fe4b0fa..f247a0b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests IConfig xEngineConfig = configSource.AddConfig("XEngine"); xEngineConfig.Set("Enabled", "true"); + xEngineConfig.Set("StartDelay", "0"); // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call // to AssemblyResolver.OnAssemblyResolve fails. diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index e07ae1c..f768cf2 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -77,7 +77,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine private IConfigSource m_ConfigSource = null; private ICompiler m_Compiler; private int m_MinThreads; - private int m_MaxThreads ; + private int m_MaxThreads; + + /// + /// Amount of time to delay before starting. + /// + private int m_StartDelay; + private int m_IdleTimeout; private int m_StackSize; private int m_SleepTime; @@ -231,6 +237,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_MaxThreads = m_ScriptConfig.GetInt("MaxThreads", 100); m_IdleTimeout = m_ScriptConfig.GetInt("IdleTimeout", 60); string priority = m_ScriptConfig.GetString("Priority", "BelowNormal"); + m_StartDelay = m_ScriptConfig.GetInt("StartDelay", 15000); m_MaxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300); m_StackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144); m_SleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", 10) * 1000; @@ -886,7 +893,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine { // This delay exists to stop mono problems where script compilation and startup would stop the sim // working properly for the session. - System.Threading.Thread.Sleep(15000); + System.Threading.Thread.Sleep(m_StartDelay); } object[] o; -- cgit v1.1 From 916e3bf886ee622e2f18d6eb74f90fee8c630471 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 11 Jul 2012 22:54:22 +0100 Subject: Where possible, use the system Encoding.ASCII and Encoding.UTF8 rather than constructing fresh copies. The encodings are thread-safe and already used in such a manner in other places. This isn't done where Byte Order Mark output is suppressed, since Encoding.UTF8 is constructed to output the BOM. --- .../CoreModules/World/Archiver/AssetsDearchiver.cs | 2 -- .../CoreModules/World/Terrain/FileLoaders/Terragen.cs | 2 +- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 3 +-- .../XmlRpcGroupsServicesConnectorModule.cs | 3 +-- .../Scripting/JsonStore/JsonStoreScriptModule.cs | 7 +++---- .../OptionalModules/Scripting/Minimodule/MRMModule.cs | 5 +---- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++------ .../Shared/Api/Implementation/OSSL_Api.cs | 3 +-- .../Region/ScriptEngine/Shared/CodeTools/Compiler.cs | 8 +++----- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 19 ++++++++----------- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 2 +- 11 files changed, 22 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs index 2c04008..8c0ef88 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs @@ -46,8 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - /// /// Store for asset data we received before we get the metadata /// diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 7a0db26..b5c7d33 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -252,7 +252,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders if (horizontalScale < 0.01d) horizontalScale = 0.01d; - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + Encoding enc = Encoding.ASCII; bs.Write(enc.GetBytes("TERRAGENTERRAIN ")); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index be8873d..7fafdc6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -823,11 +823,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice m_log.DebugFormat("[FreeSwitchVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", landName, land.LocalID, landUUID); } - System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); // slvoice handles the sip address differently if it begins with confctl, hiding it from the user in the friends list. however it also disables // the personal speech indicators as well unless some siren14-3d codec magic happens. we dont have siren143d so we'll settle for the personal speech indicator. - channelUri = String.Format("sip:conf-{0}@{1}", "x" + Convert.ToBase64String(encoding.GetBytes(landUUID)), m_freeSwitchRealm); + channelUri = String.Format("sip:conf-{0}@{1}", "x" + Convert.ToBase64String(Encoding.ASCII.GetBytes(landUUID)), m_freeSwitchRealm); lock (m_ParcelAddress) { diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 52fc27d..61aaf04 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -1120,7 +1120,6 @@ namespace Nwc.XmlRpc /// Class supporting the request side of an XML-RPC transaction. public class ConfigurableKeepAliveXmlRpcRequest : XmlRpcRequest { - private Encoding _encoding = new ASCIIEncoding(); private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer(); private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer(); private bool _disableKeepAlive = true; @@ -1153,7 +1152,7 @@ namespace Nwc.XmlRpc request.KeepAlive = !_disableKeepAlive; Stream stream = request.GetRequestStream(); - XmlTextWriter xml = new XmlTextWriter(stream, _encoding); + XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII); _serializer.Serialize(xml, this); xml.Flush(); xml.Close(); diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index 4949097..eaba816 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -425,10 +425,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore try { - System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); - string jsondata = SLUtil.ParseNotecardToString(enc.GetString(a.Data)); - int result = m_store.SetValue(storeID,path,jsondata,true) ? 1 : 0; - m_comms.DispatchReply(scriptID,result,"",reqID.ToString()); + string jsondata = SLUtil.ParseNotecardToString(Encoding.UTF8.GetString(a.Data)); + int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0; + m_comms.DispatchReply(scriptID,result, "", reqID.ToString()); return; } catch (Exception e) diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index 74f5208..03481d2 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -482,10 +482,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule // Convert to base64 // string filetext = Convert.ToBase64String(data); - - ASCIIEncoding enc = new ASCIIEncoding(); - - Byte[] buf = enc.GetBytes(filetext); + Byte[] buf = Encoding.ASCII.GetBytes(filetext); m_log.Info("MRM 9"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0a25454..0ebcd8d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10536,9 +10536,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - System.Text.UTF8Encoding enc = - new System.Text.UTF8Encoding(); - string data = enc.GetString(a.Data); + string data = Encoding.UTF8.GetString(a.Data); //m_log.Debug(data); NotecardCache.Cache(id, data); AsyncCommands. @@ -10591,9 +10589,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - System.Text.UTF8Encoding enc = - new System.Text.UTF8Encoding(); - string data = enc.GetString(a.Data); + string data = Encoding.UTF8.GetString(a.Data); //m_log.Debug(data); NotecardCache.Cache(id, data); AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index e90f577..cfa08c2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1811,8 +1811,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (a == null) return UUID.Zero; - System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); - string data = enc.GetString(a.Data); + string data = Encoding.UTF8.GetString(a.Data); NotecardCache.Cache(assetID, data); }; diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 8f2ec49..17a0d69 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.IO; +using System.Text; using Microsoft.CSharp; //using Microsoft.JScript; using Microsoft.VisualBasic; @@ -711,9 +712,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // string filetext = System.Convert.ToBase64String(data); - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - - Byte[] buf = enc.GetBytes(filetext); + Byte[] buf = Encoding.ASCII.GetBytes(filetext); FileStream sfs = File.Create(assembly + ".text"); sfs.Write(buf, 0, buf.Length); @@ -804,8 +803,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools mapstring += String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value); } - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - Byte[] mapbytes = enc.GetBytes(mapstring); + Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring); FileStream mfs = File.Create(filename); mfs.Write(mapbytes, 0, mapbytes.Length); mfs.Close(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 306090e..1c0cac7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -26,15 +26,16 @@ */ using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Lifetime; -using System.Threading; -using System.Collections; -using System.Collections.Generic; using System.Security.Policy; -using System.Reflection; -using System.Globalization; +using System.Text; +using System.Threading; using System.Xml; using OpenMetaverse; using log4net; @@ -298,13 +299,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance using (FileStream fs = File.Open(savedState, FileMode.Open, FileAccess.Read, FileShare.None)) { - System.Text.UTF8Encoding enc = - new System.Text.UTF8Encoding(); - Byte[] data = new Byte[size]; fs.Read(data, 0, size); - xml = enc.GetString(data); + xml = Encoding.UTF8.GetString(data); ScriptSerializer.Deserialize(xml, this); @@ -954,8 +952,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance try { FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); - System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); - Byte[] buf = enc.GetBytes(xml); + Byte[] buf = (new UTF8Encoding()).GetBytes(xml); fs.Write(buf, 0, buf.Length); fs.Close(); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index f768cf2..20fad05 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1763,7 +1763,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine tfs.Read(tdata, 0, tdata.Length); } - assem = new System.Text.ASCIIEncoding().GetString(tdata); + assem = Encoding.ASCII.GetString(tdata); } catch (Exception e) { -- cgit v1.1 From 743437262ed645204d9040e1705a41902860a648 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 11 Jul 2012 16:07:14 -0700 Subject: Many explanitory comments added to the link and delink code in SOG and SOP. Should have no functionality changes. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 88 ++++++++++++++++++---- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 28 +++++-- 2 files changed, 93 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index fc04761..52469a2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -451,6 +451,8 @@ namespace OpenSim.Region.Framework.Scenes } } + // Restuff the new GroupPosition into each SOP of the linkset. + // This has the affect of resetting and tainting the physics actors. SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) parts[i].GroupPosition = val; @@ -1133,6 +1135,9 @@ namespace OpenSim.Region.Framework.Scenes public void ResetChildPrimPhysicsPositions() { + // Setting this SOG's absolute position also loops through and sets the positions + // of the SOP's in this SOG's linkset. This has the side affect of making sure + // the physics world matches the simulated world. AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? // teravus: AbsolutePosition is NOT a normal property! @@ -1987,6 +1992,8 @@ namespace OpenSim.Region.Framework.Scenes LinkToGroup(objectGroup, false); } + // Link an existing group to this group. + // The group being linked need not be a linkset -- it can have just one prim. public void LinkToGroup(SceneObjectGroup objectGroup, bool insert) { // m_log.DebugFormat( @@ -1997,35 +2004,51 @@ namespace OpenSim.Region.Framework.Scenes if (objectGroup == this) return; + // 'linkPart' == the root of the group being linked into this group SceneObjectPart linkPart = objectGroup.m_rootPart; // physics flags from group to be applied to linked parts bool grpusephys = UsesPhysics; bool grptemporary = IsTemporary; + // Remember where the group being linked thought it was Vector3 oldGroupPosition = linkPart.GroupPosition; Quaternion oldRootRotation = linkPart.RotationOffset; + // A linked SOP remembers its location and rotation relative to the root of a group. + // Convert the root of the group being linked to be relative to the + // root of the group being linked to. + // Note: Some of the assignments have complex side effects. + + // First move the new group's root SOP's position to be relative to ours + // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, + // this code can be reordered to have a more logical flow.) linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; + // Assign the new parent to the root of the old group linkPart.ParentID = m_rootPart.LocalId; + // Now that it's a child, it's group position is our root position linkPart.GroupPosition = AbsolutePosition; - Vector3 axPos = linkPart.OffsetPosition; + Vector3 axPos = linkPart.OffsetPosition; + // Rotate the linking root SOP's position to be relative to the new root prim Quaternion parentRot = m_rootPart.RotationOffset; axPos *= Quaternion.Inverse(parentRot); - linkPart.OffsetPosition = axPos; + + // Make the linking root SOP's rotation relative to the new root prim Quaternion oldRot = linkPart.RotationOffset; Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; linkPart.RotationOffset = newRot; - linkPart.ParentID = m_rootPart.LocalId; - + // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. + // Now that we know this SOG has at least two SOPs in it, the new root + // SOP becomes the first in the linkset. if (m_rootPart.LinkNum == 0) m_rootPart.LinkNum = 1; lock (m_parts.SyncRoot) { + // Calculate the new link number for the old root SOP int linkNum; if (insert) { @@ -2041,6 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes linkNum = PrimCount + 1; } + // Add the old root SOP as a part in our group's list m_parts.Add(linkPart.UUID, linkPart); linkPart.SetParent(this); @@ -2048,6 +2072,8 @@ namespace OpenSim.Region.Framework.Scenes // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); + + // If the added SOP is physical, also tell the physics engine about the link relationship. if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) { linkPart.PhysActor.link(m_rootPart.PhysActor); @@ -2056,20 +2082,26 @@ namespace OpenSim.Region.Framework.Scenes linkPart.LinkNum = linkNum++; + // Get a list of the SOP's in the old group in order of their linknum's. SceneObjectPart[] ogParts = objectGroup.Parts; Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) { return a.LinkNum - b.LinkNum; }); + // Add each of the SOP's from the old linkset to our linkset for (int i = 0; i < ogParts.Length; i++) { SceneObjectPart part = ogParts[i]; if (part.UUID != objectGroup.m_rootPart.UUID) { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); - // let physics know + + // Update the physics flags for the newly added SOP + // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); + + // If the added SOP is physical, also tell the physics engine about the link relationship. if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) { part.PhysActor.link(m_rootPart.PhysActor); @@ -2080,6 +2112,7 @@ namespace OpenSim.Region.Framework.Scenes } } + // Now that we've aquired all of the old SOG's parts, remove the old SOG from the scene. m_scene.UnlinkSceneObject(objectGroup, true); objectGroup.IsDeleted = true; @@ -2152,7 +2185,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race /// condition. But currently there is no - /// alternative method that does take a lonk to delink a single prim. + /// alternative method that does take a lock to delink a single prim. /// /// /// @@ -2165,6 +2198,7 @@ namespace OpenSim.Region.Framework.Scenes linkPart.ClearUndoState(); + Vector3 worldPos = linkPart.GetWorldPosition(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object @@ -2174,6 +2208,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = m_parts.GetArray(); + // Rejigger the linknum's of the remaining SOP's to fill any gap if (parts.Length == 1 && RootPart != null) { // Single prim left @@ -2195,22 +2230,31 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor linkPartPa = linkPart.PhysActor; + // Remove the SOP from the physical scene. + // If the new SOG is physical, it is re-created later. + // (There is a problem here in that we have not yet told the physics + // engine about the delink. Someday, linksets should be made first + // class objects in the physics engine interface). if (linkPartPa != null) m_scene.PhysicsScene.RemovePrim(linkPartPa); // We need to reset the child part's position // ready for life as a separate object after being a part of another object - Quaternion parentRot = m_rootPart.RotationOffset; + /* This commented out code seems to recompute what GetWorldPosition already does. + * Replace with a call to GetWorldPosition (before unlinking) + Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; - axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); - + */ + linkPart.GroupPosition = worldPos; + linkPart.OffsetPosition = Vector3.Zero; linkPart.RotationOffset = worldRot; + // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); @@ -2239,42 +2283,56 @@ namespace OpenSim.Region.Framework.Scenes m_isBackedUp = false; } + // This links an SOP from a previous linkset into my linkset. + // The trick is that the SOP's position and rotation are relative to the old root SOP's + // so we are passed in the position and rotation of the old linkset so this can + // unjigger this SOP's position and rotation from the previous linkset and + // then make them relative to my linkset root. private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum) { Quaternion parentRot = oldGroupRotation; Quaternion oldRot = part.RotationOffset; - Quaternion worldRot = parentRot * oldRot; - - parentRot = oldGroupRotation; + // Move our position to not be relative to the old parent Vector3 axPos = part.OffsetPosition; - axPos *= parentRot; part.OffsetPosition = axPos; part.GroupPosition = oldGroupPosition + part.OffsetPosition; part.OffsetPosition = Vector3.Zero; + + // Compution our rotation to be not relative to the old parent + Quaternion worldRot = parentRot * oldRot; part.RotationOffset = worldRot; + // Add this SOP to our linkset part.SetParent(this); part.ParentID = m_rootPart.LocalId; - m_parts.Add(part.UUID, part); part.LinkNum = linkNum; + // Compute the new position of this SOP relative to the group position part.OffsetPosition = part.GroupPosition - AbsolutePosition; - Quaternion rootRotation = m_rootPart.RotationOffset; + // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. + // It would have the affect of setting the physics engine position multiple + // times. In theory, that is not necessary but I don't have a good linkset + // test to know that cleaning up this code wouldn't break things.) + // Rotate the relative position by the rotation of the group + Quaternion rootRotation = m_rootPart.RotationOffset; Vector3 pos = part.OffsetPosition; pos *= Quaternion.Inverse(rootRotation); part.OffsetPosition = pos; + // Compute the SOP's rotation relative to the rotation of the group. parentRot = m_rootPart.RotationOffset; oldRot = part.RotationOffset; Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; part.RotationOffset = newRot; + // Since this SOP's state has changed, push those changes into the physics engine + // and the simulator. part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b3f11a7..4b2fede 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -693,9 +693,11 @@ namespace OpenSim.Region.Framework.Scenes { // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; + // If physical and the root prim of a linkset, the position of the group is what physics thinks. if (actor != null && ParentID == 0) m_groupPosition = actor.Position; + // If I'm an attachment, my position is reported as the position of who I'm attached to if (ParentGroup.IsAttachment) { ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); @@ -721,7 +723,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - // To move the child prim in respect to the group position and rotation we have to calculate + // The physics engine always sees all objects (root or linked) in world coordinates. actor.Position = GetWorldPosition(); actor.Orientation = GetWorldRotation(); } @@ -795,6 +797,8 @@ namespace OpenSim.Region.Framework.Scenes { // We don't want the physics engine mucking up the rotations in a linkset PhysicsActor actor = PhysActor; + // If this is a root of a linkset, the real rotation is what the physics engine thinks. + // If not a root prim, the offset rotation is computed by SOG and is relative to the root. if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) { if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f @@ -1980,14 +1984,20 @@ namespace OpenSim.Region.Framework.Scenes /// A Linked Child Prim objects position in world public Vector3 GetWorldPosition() { - Quaternion parentRot = ParentGroup.RootPart.RotationOffset; - Vector3 axPos = OffsetPosition; - axPos *= parentRot; - Vector3 translationOffsetPosition = axPos; - if(_parentID == 0) - return GroupPosition; + Vector3 ret; + if (_parentID == 0) + // if a root SOP, my position is what it is + ret = GroupPosition; else - return ParentGroup.AbsolutePosition + translationOffsetPosition; + { + // If a child SOP, my position is relative to the root SOP so take + // my info and add the root's position and rotation to + // get my world position. + Quaternion parentRot = ParentGroup.RootPart.RotationOffset; + Vector3 translationOffsetPosition = OffsetPosition * parentRot; + ret = ParentGroup.AbsolutePosition + translationOffsetPosition; + } + return ret; } /// @@ -2004,6 +2014,8 @@ namespace OpenSim.Region.Framework.Scenes } else { + // A child SOP's rotation is relative to the root SOP's rotation. + // Combine them to get my absolute rotation. Quaternion parentRot = ParentGroup.RootPart.RotationOffset; Quaternion oldRot = RotationOffset; newRot = parentRot * oldRot; -- cgit v1.1