Merge branch 'master' into careminster

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

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
}
}