mirror of
https://github.com/opensim/opensim.git
synced 2026-08-09 02:36:00 +08:00
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:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user