Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
avinationmerge
Melanie 2012-10-30 01:02:20 +00:00
commit 48569e856a
13 changed files with 486 additions and 308 deletions

View File

@ -192,8 +192,19 @@ namespace OpenSim.Framework.Servers
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
m_console.Commands.AddCommand("General", false, "force gc",
"force gc",
"Manually invoke runtime garbage collection. For debugging purposes",
HandleForceGc);
}
}
private void HandleForceGc(string module, string[] args)
{
MainConsole.Instance.Output("Manually invoking runtime garbage collection");
GC.Collect();
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing

View File

@ -548,7 +548,7 @@ namespace OpenSim.Framework
/// <summary>
/// Determines whether a point is inside a bounding box.
/// </summary>
/// <param name='v'>/param>
/// <param name='v'></param>
/// <param name='min'></param>
/// <param name='max'></param>
/// <returns></returns>

View File

@ -1111,7 +1111,7 @@ namespace OpenSim
aCircuit.Name,
aCircuit.child ? "child" : "root",
aCircuit.circuitcode.ToString(),
aCircuit.IPAddress.ToString(),
aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
aCircuit.Viewer);
});

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -24,56 +24,110 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using log4net;
using Mono.Addins;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using System.Reflection;
using log4net;
namespace OpenSim.Region.CoreModules.World.Sound
{
public class SoundModule : IRegionModule, ISoundModule
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
public class SoundModule : INonSharedRegionModule, ISoundModule
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_scene;
public void Initialise(Scene scene, IConfigSource source)
private static readonly ILog m_log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
public bool Enabled { get; private set; }
public float MaxDistance { get; private set; }
#region INonSharedRegionModule
public void Initialise(IConfigSource configSource)
{
IConfig config = configSource.Configs["Sounds"];
if (config == null)
{
Enabled = true;
MaxDistance = 100.0f;
}
else
{
Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
Path.GetFileName(Assembly.GetExecutingAssembly().Location)
+ ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
MaxDistance = config.GetFloat("MaxDistance", 100.0f);
}
}
public void AddRegion(Scene scene) { }
public void RemoveRegion(Scene scene)
{
m_scene.EventManager.OnClientLogin -= OnNewClient;
}
public void RegionLoaded(Scene scene)
{
if (!Enabled)
return;
m_scene = scene;
m_scene.EventManager.OnNewClient += OnNewClient;
m_scene.EventManager.OnClientLogin += OnNewClient;
m_scene.RegisterModuleInterface<ISoundModule>(this);
}
public void PostInitialise() {}
public void Close() {}
public void Close() { }
public Type ReplaceableInterface
{
get { return typeof(ISoundModule); }
}
public string Name { get { return "Sound Module"; } }
public bool IsSharedModule { get { return false; } }
#endregion
#region Event Handlers
private void OnNewClient(IClientAPI client)
{
client.OnSoundTrigger += TriggerSound;
}
#endregion
#region ISoundModule
public virtual void PlayAttachedSound(
UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
{
SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
if (part == null)
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
SceneObjectGroup grp = part.ParentGroup;
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
if (dis > 100.0) // Max audio distance
if (dis > MaxDistance) // Max audio distance
return;
if (grp.IsAttachment)
@ -85,26 +139,22 @@ namespace OpenSim.Region.CoreModules.World.Sound
dis = 0;
}
float thisSpGain;
// Scale by distance
if (radius == 0)
thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else
thisSpGain = (float)((double)gain * ((radius - dis) / radius));
double thisSpGain = gain * ((radius - dis) / radius);
sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags);
sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
ownerID, (float)thisSpGain, flags);
});
}
public virtual void TriggerSound(
UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
{
SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
if (part == null)
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
{
ScenePresence sp;
if (!m_scene.TryGetScenePresence(objectID, out sp))
if (!m_scene.TryGetScenePresence(ownerID, out sp))
return;
}
else
@ -118,24 +168,207 @@ namespace OpenSim.Region.CoreModules.World.Sound
}
}
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
if (dis > 100.0) // Max audio distance
if (dis > MaxDistance) // Max audio distance
return;
float thisSpGain;
// Scale by distance
if (radius == 0)
thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else
thisSpGain = (float)((double)gain * ((radius - dis) / radius));
double thisSpGain = gain * ((radius - dis) / radius);
sp.ControllingClient.SendTriggeredSound(
soundId, ownerID, objectID, parentID, handle, position, thisSpGain);
sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
objectID, parentID, handle, position,
(float)thisSpGain);
});
}
public virtual void StopSound(UUID objectID)
{
SceneObjectPart m_host;
if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
return;
StopSound(m_host);
}
private static void StopSound(SceneObjectPart m_host)
{
m_host.AdjustSoundGain(0);
// Xantor 20080528: Clear prim data of sound instead
if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
{
if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
{
foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
{
part.Sound = UUID.Zero;
part.SoundFlags = 1 << 5;
part.SoundRadius = 0;
part.ScheduleFullUpdate();
part.SendFullUpdateToAllClients();
}
m_host.ParentGroup.LoopSoundMasterPrim = null;
m_host.ParentGroup.LoopSoundSlavePrims.Clear();
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundFlags = 1 << 5;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundFlags = 1 << 5;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
{
SceneObjectPart part;
if (soundID == UUID.Zero
|| !m_scene.TryGetSceneObjectPart(objectID, out part))
{
return;
}
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
});
}
// Xantor 20080528 we should do this differently.
// 1) apply the sound to the object
// 2) schedule full update
// just sending the sound out once doesn't work so well when other avatars come in view later on
// or when the prim gets moved, changed, sat on, whatever
// see large number of mantises (mantes?)
// 20080530 Updated to remove code duplication
// 20080530 Stop sound if there is one, otherwise volume only changes don't work
public void LoopSound(UUID objectID, UUID soundID,
double volume, double radius, bool isMaster)
{
SceneObjectPart m_host;
if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
return;
if (isMaster)
m_host.ParentGroup.LoopSoundMasterPrim = m_host;
if (m_host.Sound != UUID.Zero)
StopSound(m_host);
m_host.Sound = soundID;
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = radius;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
public void SendSound(UUID objectID, UUID soundID, double volume,
bool triggered, byte flags, float radius, bool useMaster,
bool isMaster)
{
if (soundID == UUID.Zero)
return;
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
volume = Util.Clip((float)volume, 0, 1);
UUID parentID = part.ParentGroup.UUID;
Vector3 position = part.AbsolutePosition; // region local
ulong regionHandle = m_scene.RegionInfo.RegionHandle;
if (useMaster)
{
if (isMaster)
{
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
part.ParentGroup.PlaySoundMasterPrim = part;
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
{
position = prim.AbsolutePosition; // region local
if (triggered)
TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
}
part.ParentGroup.PlaySoundSlavePrims.Clear();
part.ParentGroup.PlaySoundMasterPrim = null;
}
else
{
part.ParentGroup.PlaySoundSlavePrims.Add(part);
}
}
else
{
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
}
}
public void TriggerSoundLimited(UUID objectID, UUID sound,
double volume, Vector3 min, Vector3 max)
{
if (sound == UUID.Zero)
return;
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
double dis = Util.GetDistanceTo(sp.AbsolutePosition,
part.AbsolutePosition);
if (dis > MaxDistance) // Max audio distance
return;
else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
return;
// Scale by distance
double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance);
sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID,
part.UUID, part.ParentGroup.UUID,
m_scene.RegionInfo.RegionHandle,
part.AbsolutePosition, (float)thisSpGain);
});
}
#endregion
}
}

View File

@ -32,9 +32,96 @@ namespace OpenSim.Region.Framework.Interfaces
{
public interface ISoundModule
{
void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius);
/// <summary>
/// Maximum distance between a sound source and a recipient.
/// </summary>
float MaxDistance { get; }
/// <summary>
/// Play a sound from an object.
/// </summary>
/// <param name="soundID">Sound asset ID</param>
/// <param name="ownerID">Sound source owner</param>
/// <param name="objectID">Sound source ID</param>
/// <param name="gain">Sound volume</param>
/// <param name="position">Sound source position</param>
/// <param name="flags">Sound flags</param>
/// <param name="radius">
/// Radius used to affect gain over distance.
/// </param>
void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID,
double gain, Vector3 position, byte flags, float radius);
/// <summary>
/// Trigger a sound in the scene.
/// </summary>
/// <param name="soundId">Sound asset ID</param>
/// <param name="ownerID">Sound source owner</param>
/// <param name="objectID">Sound source ID</param>
/// <param name="parentID">Sound source parent.</param>
/// <param name="gain">Sound volume</param>
/// <param name="position">Sound source position</param>
/// <param name="handle"></param>
/// <param name="radius">
/// Radius used to affect gain over distance.
/// </param>
void TriggerSound(
UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius);
UUID soundId, UUID ownerID, UUID objectID, UUID parentID,
double gain, Vector3 position, UInt64 handle, float radius);
/// <summary>
/// Stop sounds eminating from an object.
/// </summary>
/// <param name="objectID">Sound source ID</param>
void StopSound(UUID objectID);
/// <summary>
/// Preload sound to viewers within range.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="soundID">Sound asset ID</param>
/// <param name="radius">
/// Radius used to determine which viewers should preload the sound.
/// </param>
void PreloadSound(UUID objectID, UUID soundID, float radius);
/// <summary>
/// Loop specified sound at specified volume with specified radius,
/// optionally declaring object as new sync master.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="soundID">Sound asset ID</param>
/// <param name="gain">Sound volume</param>
/// <param name="radius">Sound radius</param>
/// <param name="isMaster">Set object to sync master if true</param>
void LoopSound(UUID objectID, UUID soundID, double gain,
double radius, bool isMaster);
/// <summary>
/// Trigger or play an attached sound in this part's inventory.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="triggered">Triggered or not.</param>
/// <param name="flags"></param>
/// <param name="radius">Sound radius</param>
/// <param name="useMaster">Play using sound master</param>
/// <param name="isMaster">Play as sound master</param>
void SendSound(UUID objectID, UUID sound, double volume,
bool triggered, byte flags, float radius, bool useMaster,
bool isMaster);
/// <summary>
/// Trigger a sound to be played to all agents within an axis-aligned
/// bounding box.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="min">AABB bottom south-west corner</param>
/// <param name="max">AABB top north-east corner</param>
void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
Vector3 min, Vector3 max);
}
}

View File

@ -3552,9 +3552,10 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
// We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred
// We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
// simultaneously.
m_authenticateHandler.RemoveCircuit(acd.circuitcode);
// We also need to remove by agent ID since NPCs will have no circuit code.
m_authenticateHandler.RemoveCircuit(agentID);
}
}

View File

@ -2895,38 +2895,6 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleTerseUpdate();
}
public void PreloadSound(string sound)
{
// UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID soundID = UUID.Zero;
if (!UUID.TryParse(sound, out soundID))
{
//Trys to fetch sound id from prim's inventory.
//Prim's inventory doesn't support non script items yet
TaskInventory.LockItemsForRead(true);
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound)
{
soundID = item.Value.ItemID;
break;
}
}
TaskInventory.LockItemsForRead(false);
}
ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100))
sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
});
}
public void RemFlag(PrimFlags flag)
{
// PrimFlags prevflag = Flags;
@ -3297,126 +3265,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/// <summary>
/// Trigger or play an attached sound in this part's inventory.
/// </summary>
/// <param name="sound"></param>
/// <param name="volume"></param>
/// <param name="triggered"></param>
/// <param name="flags"></param>
public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster)
{
if (volume > 1)
volume = 1;
if (volume < 0)
volume = 0;
UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID parentID = ParentGroup.UUID;
UUID soundID = UUID.Zero;
Vector3 position = AbsolutePosition; // region local
ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
if (!UUID.TryParse(sound, out soundID))
{
// search sound file from inventory
TaskInventory.LockItemsForRead(true);
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
{
soundID = item.Value.ItemID;
break;
}
}
TaskInventory.LockItemsForRead(false);
}
if (soundID == UUID.Zero)
return;
ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
if (soundModule != null)
{
if (useMaster)
{
if (isMaster)
{
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
ParentGroup.PlaySoundMasterPrim = this;
ownerID = OwnerID;
objectID = ParentGroup.RootPart.UUID;
parentID = ParentGroup.UUID;
position = AbsolutePosition; // region local
regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
{
ownerID = prim.OwnerID;
objectID = prim.ParentGroup.RootPart.UUID;
parentID = prim.ParentGroup.UUID;
position = prim.AbsolutePosition; // region local
regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
}
ParentGroup.PlaySoundSlavePrims.Clear();
ParentGroup.PlaySoundMasterPrim = null;
}
else
{
ParentGroup.PlaySoundSlavePrims.Add(this);
}
}
else
{
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
}
}
}
public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
{
if (soundID == UUID.Zero)
return;
ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
if (soundModule == null)
return;
if (volume > 1)
volume = 1;
if (volume < 0)
volume = 0;
int now = Util.EnvironmentTickCount();
if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
return;
LastColSoundSentTime = now;
UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID parentID = ParentGroup.UUID;
ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
}
/// <summary>
/// Send a terse update to all clients
/// </summary>

View File

@ -75,8 +75,9 @@ namespace OpenSim.Region.Framework.Scenes
{
// ~ScenePresence()
// {
// m_log.Debug("[SCENE PRESENCE] Destructor called");
// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
// }
private void TriggerScenePresenceUpdated()
{
if (m_scene != null)

View File

@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
{
if (!CanEdit())
return;
GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false);
ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
if (module != null)
{
module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
}
}
#endregion

View File

@ -117,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
Assert.That(npc, Is.Not.Null);
Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
IClientAPI client;
Assert.That(m_scene.TryGetClient(npcId, out client), Is.True);
// Have to account for both SP and NPC.
Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2));
}
[Test]
@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
Assert.That(deletedNpc, Is.Null);
IClientAPI client;
Assert.That(m_scene.TryGetClient(npcId, out client), Is.False);
// Have to account for SP still present.
Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
}
[Test]

View File

@ -3341,7 +3341,6 @@ Console.WriteLine(" JointCreateFixed");
m_material = pMaterial;
}
private void CheckMeshAsset()
{
if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@ -3351,12 +3350,12 @@ Console.WriteLine(" JointCreateFixed");
{
RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
if (assetProvider != null)
assetProvider(_pbs.SculptTexture, MeshAssetReveived);
assetProvider(_pbs.SculptTexture, MeshAssetReceived);
});
}
}
void MeshAssetReveived(AssetBase asset)
private void MeshAssetReceived(AssetBase asset)
{
if (asset.Data != null && asset.Data.Length > 0)
{

View File

@ -113,6 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
new Dictionary<UUID, UserInfoCacheEntry>();
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
protected ISoundModule m_SoundModule = null;
// protected Timer m_ShoutSayTimer;
protected int m_SayShoutCount = 0;
@ -160,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_TransferModule =
m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
AsyncCommands = new AsyncCommandManager(ScriptEngine);
}
@ -427,6 +429,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return key;
}
/// <summary>
/// Return the UUID of the asset matching the specified key or name
/// and asset type.
/// </summary>
/// <param name="k"></param>
/// <param name="type"></param>
/// <returns></returns>
protected UUID KeyOrName(string k, AssetType type)
{
UUID key;
if (!UUID.TryParse(k, out key))
{
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
if (item != null && item.Type == (int)type)
key = item.AssetID;
}
else
{
lock (m_host.TaskInventory)
{
foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
{
if (item.Value.Type == (int)type && item.Value.Name == k)
{
key = item.Value.ItemID;
break;
}
}
}
}
return key;
}
//These are the implementations of the various ll-functions used by the LSL scripts.
public LSL_Float llSin(double f)
{
@ -2279,8 +2317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetPos()
{
m_host.AddScriptLPS(1);
Vector3 pos = m_host.GetWorldPosition();
return new LSL_Vector(pos.X, pos.Y, pos.Z);
return m_host.GetWorldPosition();
}
public LSL_Vector llGetLocalPos()
@ -2638,63 +2675,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range
m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false);
if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, false, 0,
0, false, false);
}
}
// Xantor 20080528 we should do this differently.
// 1) apply the sound to the object
// 2) schedule full update
// just sending the sound out once doesn't work so well when other avatars come in view later on
// or when the prim gets moved, changed, sat on, whatever
// see large number of mantises (mantes?)
// 20080530 Updated to remove code duplication
// 20080530 Stop sound if there is one, otherwise volume only changes don't work
public void llLoopSound(string sound, double volume)
{
m_host.AddScriptLPS(1);
if (m_host.Sound != UUID.Zero)
llStopSound();
m_host.Sound = KeyOrName(sound);
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
if (m_SoundModule != null)
{
m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
volume, 20, false);
}
}
public void llLoopSoundMaster(string sound, double volume)
{
m_host.AddScriptLPS(1);
m_host.ParentGroup.LoopSoundMasterPrim = m_host;
lock (m_host.ParentGroup.LoopSoundSlavePrims)
if (m_SoundModule != null)
{
foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims)
{
if (prim.Sound != UUID.Zero)
llStopSound();
prim.Sound = KeyOrName(sound);
prim.SoundGain = volume;
prim.SoundFlags = 1; // looping
prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
prim.ScheduleFullUpdate();
prim.SendFullUpdateToAllClients();
}
m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
volume, 20, true);
}
if (m_host.Sound != UUID.Zero)
llStopSound();
m_host.Sound = KeyOrName(sound);
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
public void llLoopSoundSlave(string sound, double volume)
@ -2711,61 +2717,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range
m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false);
if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, false, 0,
0, true, false);
}
}
public void llTriggerSound(string sound, double volume)
{
m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range
m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false);
// send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
false, false);
}
}
// Xantor 20080528: Clear prim data of sound instead
public void llStopSound()
{
m_host.AddScriptLPS(1);
if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
{
if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
{
foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
{
part.Sound = UUID.Zero;
part.SoundGain = 0;
part.SoundFlags = 0;
part.SoundRadius = 0;
part.ScheduleFullUpdate();
part.SendFullUpdateToAllClients();
}
m_host.ParentGroup.LoopSoundMasterPrim = null;
m_host.ParentGroup.LoopSoundSlavePrims.Clear();
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
if (m_SoundModule != null)
m_SoundModule.StopSound(m_host.UUID);
}
public void llPreloadSound(string sound)
{
m_host.AddScriptLPS(1);
m_host.PreloadSound(sound);
if (m_SoundModule != null)
m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
ScriptSleep(1000);
}
@ -4747,16 +4731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
// TODO: Parameter check logic required.
UUID soundId = UUID.Zero;
if (!UUID.TryParse(impact_sound, out soundId))
{
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
if (item != null && item.Type == (int)AssetType.Sound)
soundId = item.AssetID;
}
m_host.CollisionSound = soundId;
m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound);
m_host.CollisionSoundVolume = (float)impact_volume;
m_host.CollisionSoundType = 1;
}
@ -6318,10 +6293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_Vector bottom_south_west)
{
m_host.AddScriptLPS(1);
float radius1 = (float)llVecDist(llGetPos(), top_north_east);
float radius2 = (float)llVecDist(llGetPos(), bottom_south_west);
float radius = Math.Abs(radius1 - radius2);
m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false);
if (m_SoundModule != null)
{
m_SoundModule.TriggerSoundLimited(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume,
bottom_south_west, top_north_east);
}
}
public void llEjectFromLand(string pest)

View File

@ -1683,5 +1683,12 @@ Enabled = False
;; default is module is disabled at the top level
AutoBackupModuleEnabled = false
[Sounds]
;; {Module} {} {Implementation of ISoundModule to use.} {OpenSim.Region.CoreModules.dll:SoundModule}
Module = OpenSim.Region.CoreModules.dll:SoundModule
;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
MaxDistance = 100.0
[Modules]
Include-modules = "addon-modules/*/config/*.ini"