From 54a27f9f5c556e518c2ba18b9a5494d517dfd041 Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Tue, 31 Mar 2009 02:33:19 +0000 Subject: Thank you kindly, MCortez for a patch that: With some support from HomerH, this patch adds support for Wind Model plugins via the mono.Addin framework. * Adds console & OSSL access to Wind Parameters * Adds plug-in support for custom wind models * Provides two example Wind Model plug-ins Documentation for the wind module is temporarily located at http://code.google.com/p/flotsam/wiki/CoreWindModule [^] -- will move this documentation to http://opensimulator.org [^] after the patch has been committed. --- .../CoreModules/Resources/Wind.Models.addin.xml | 12 + .../CoreModules/World/Wind/IWindModelPlugin.cs | 56 +++ .../World/Wind/Plugins/ConfigurableWind.cs | 211 +++++++++++ .../World/Wind/Plugins/SimpleRandomWind.cs | 139 +++++++ .../Region/CoreModules/World/Wind/WindModule.cs | 410 ++++++++++++++++----- OpenSim/Region/Framework/Interfaces/IWindModule.cs | 15 + .../Shared/Api/Implementation/OSSL_Api.cs | 45 ++- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 5 + .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 16 + bin/OpenSim.addin.xml | 3 + prebuild.xml | 7 +- 11 files changed, 817 insertions(+), 102 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Resources/Wind.Models.addin.xml create mode 100644 OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs create mode 100644 OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs create mode 100644 OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs diff --git a/OpenSim/Region/CoreModules/Resources/Wind.Models.addin.xml b/OpenSim/Region/CoreModules/Resources/Wind.Models.addin.xml new file mode 100644 index 0000000..972f795 --- /dev/null +++ b/OpenSim/Region/CoreModules/Resources/Wind.Models.addin.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs b/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs new file mode 100644 index 0000000..29b0ed5 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Wind/IWindModelPlugin.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +using Nini.Config; +using OpenSim.Framework; +using OpenMetaverse; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Wind +{ + public interface IWindModelPlugin : IPlugin + { + /// + /// Brief description of this plugin's wind model + /// + string Description { get; } + + /// + /// Provides access to the wind configuration, if any. + /// + void WindConfig(Scene scene, IConfig windConfig); + + /// + /// Update wind. + /// + void WindUpdate(uint frame); + + /// + /// Returns the wind vector at the given local region coordinates. + /// + Vector3 WindSpeed(float x, float y, float z); + + /// + /// Generate a 16 x 16 Vector2 array of wind speeds for LL* based viewers + /// + /// Must return a Vector2[256] + Vector2[] WindLLClientArray(); + + /// + /// Retrieve a list of parameter/description pairs. + /// + /// + Dictionary WindParams(); + + /// + /// Set the specified parameter + /// + void WindParamSet(string param, float value); + + /// + /// Get the specified parameter + /// + float WindParamGet(string param); + + } +} diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs new file mode 100644 index 0000000..2f5cc31 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +using log4net; +using OpenMetaverse; + +using OpenSim.Region.CoreModules.World.Wind; + +namespace OpenSim.Region.CoreModules.World.Wind.Plugins +{ + class ConfigurableWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Vector2[] m_windSpeeds = new Vector2[16 * 16]; + private Random m_rndnums = new Random(Environment.TickCount); + + private float m_avgStrength = 5.0f; // Average magnitude of the wind vector + private float m_avgDirection = 0.0f; // Average direction of the wind in degrees + private float m_varStrength = 5.0f; // Max Strength Variance + private float m_varDirection = 30.0f;// Max Direction Variance + private float m_rateChange = 1.0f; // + + private Vector2 m_curPredominateWind = new Vector2(); + + + + #region IPlugin Members + + public string Version + { + get { return "1.0.0.0"; } + } + + public string Name + { + get { return "ConfigurableWind"; } + } + + public void Initialise() + { + + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + m_windSpeeds = null; + } + + #endregion + + #region IWindModelPlugin Members + + public void WindConfig(OpenSim.Region.Framework.Scenes.Scene scene, Nini.Config.IConfig windConfig) + { + if( windConfig != null ) + { + // Uses strength value if avg_strength not specified + m_avgStrength = windConfig.GetFloat("strength", 5.0F); + m_avgStrength = windConfig.GetFloat("avg_strength", 5.0F); + + m_avgDirection = windConfig.GetFloat("avg_direction", 0.0F); + m_varStrength = windConfig.GetFloat("var_strength", 5.0F); + m_varDirection = windConfig.GetFloat("var_direction", 30.0F); + m_rateChange = windConfig.GetFloat("rate_change", 1.0F); + + LogSettings(); + } + } + + public void WindUpdate(uint frame) + { + double avgAng = m_avgDirection * (Math.PI/180.0f); + double varDir = m_varDirection * (Math.PI/180.0f); + + // Prevailing wind algorithm + // Inspired by Kanker Greenacre + + // TODO: + // * This should probably be based on in-world time. + // * should probably move all these local variables to class members and constants + double time = DateTime.Now.TimeOfDay.Seconds / 86400; + + double theta = time * (2 * Math.PI) * m_rateChange; + + double offset = Math.Sin(theta) * Math.Sin(theta*2) * Math.Sin(theta*9) * Math.Cos(theta*4); + + double windDir = avgAng + (varDir * offset); + + offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3); + double windSpeed = m_avgStrength + (m_varStrength * offset); + + if (windSpeed<0) + windSpeed=0; + + + + m_curPredominateWind.X = (float)Math.Cos(windDir); + m_curPredominateWind.Y = (float)Math.Sin(windDir); + + m_curPredominateWind.Normalize(); + m_curPredominateWind.X *= (float)windSpeed; + m_curPredominateWind.Y *= (float)windSpeed; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + m_windSpeeds[y * 16 + x] = m_curPredominateWind; + } + } + } + + public Vector3 WindSpeed(float fX, float fY, float fZ) + { + return new Vector3(m_curPredominateWind, 0.0f); + } + + public Vector2[] WindLLClientArray() + { + return m_windSpeeds; + } + + public string Description + { + get + { + return "Provides a predominate wind direction that can change within configured variances for direction and speed."; + } + } + + public System.Collections.Generic.Dictionary WindParams() + { + Dictionary Params = new Dictionary(); + + Params.Add("avgStrength", "average wind strength"); + Params.Add("avgDirection", "average wind direction in degrees"); + Params.Add("varStrength", "allowable variance in wind strength"); + Params.Add("varDirection", "allowable variance in wind direction in +/- degrees"); + Params.Add("rateChange", "rate of change"); + + return Params; + } + + public void WindParamSet(string param, float value) + { + switch (param) + { + case "avgStrength": + m_avgStrength = value; + break; + case "avgDirection": + m_avgDirection = value; + break; + case "varStrength": + m_varStrength = value; + break; + case "varDirection": + m_varDirection = value; + break; + case "rateChange": + m_rateChange = value; + break; + } + } + + public float WindParamGet(string param) + { + switch (param) + { + case "avgStrength": + return m_avgStrength; + case "avgDirection": + return m_avgDirection; + case "varStrength": + return m_varStrength; + case "varDirection": + return m_varDirection; + case "rateChange": + return m_rateChange; + default: + throw new Exception(String.Format("Unknown {0} parameter {1}", this.Name, param)); + + } + } + + + + #endregion + + + private void LogSettings() + { + m_log.InfoFormat("[ConfigurableWind] Average Strength : {0}", m_avgStrength); + m_log.InfoFormat("[ConfigurableWind] Average Direction : {0}", m_avgDirection); + m_log.InfoFormat("[ConfigurableWind] Varience Strength : {0}", m_varStrength); + m_log.InfoFormat("[ConfigurableWind] Varience Direction : {0}", m_varDirection); + m_log.InfoFormat("[ConfigurableWind] Rate Change : {0}", m_rateChange); + } + + #region IWindModelPlugin Members + + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs new file mode 100644 index 0000000..040a3c4 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; + +using OpenMetaverse; + + +namespace OpenSim.Region.CoreModules.World.Wind.Plugins +{ + class SimpleRandomWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin + { + private Vector2[] m_windSpeeds = new Vector2[16 * 16]; + private float m_strength = 1.0f; + private Random m_rndnums = new Random(Environment.TickCount); + + + #region IPlugin Members + + public string Version + { + get { return "1.0.0.0"; } + } + + public string Name + { + get { return "SimpleRandomWind"; } + } + + public void Initialise() + { + + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + m_windSpeeds = null; + } + + #endregion + + #region IWindModelPlugin Members + + public void WindConfig(OpenSim.Region.Framework.Scenes.Scene scene, Nini.Config.IConfig windConfig) + { + if( windConfig != null ) + { + if( windConfig.Contains("strength") ) + { + m_strength = windConfig.GetFloat("strength", 1.0F); + } + } + } + + public void WindUpdate(uint frame) + { + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 + m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 + m_windSpeeds[y * 16 + x].X *= m_strength; + m_windSpeeds[y * 16 + x].Y *= m_strength; + } + } + } + + public Vector3 WindSpeed(float fX, float fY, float fZ) + { + Vector3 windVector = new Vector3(0.0f, 0.0f, 0.0f); + + int x = (int)fX / 16; + int y = (int)fY / 16; + + if (x < 0) x = 0; + if (x > 15) x = 15; + if (y < 0) y = 0; + if (y > 15) y = 15; + + if (m_windSpeeds != null) + { + windVector.X = m_windSpeeds[y * 16 + x].X; + windVector.Y = m_windSpeeds[y * 16 + x].Y; + } + + return windVector; + + } + + public Vector2[] WindLLClientArray() + { + return m_windSpeeds; + } + + public string Description + { + get + { + return "Provides a simple wind model that creates random wind of a given strength in 16m x 16m patches."; + } + } + + public System.Collections.Generic.Dictionary WindParams() + { + Dictionary Params = new Dictionary(); + + Params.Add("strength", "wind strength"); + + return Params; + } + + public void WindParamSet(string param, float value) + { + switch (param) + { + case "strength": + m_strength = value; + break; + } + } + + public float WindParamGet(string param) + { + switch (param) + { + case "strength": + return m_strength; + default: + throw new Exception(String.Format("Unknown {0} parameter {1}", this.Name, param)); + } + } + + #endregion + + } +} diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index 87e6fd9..26901a4 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -27,57 +27,125 @@ using System; using System.Collections.Generic; +using System.Reflection; +using log4net; +using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Wind; + namespace OpenSim.Region.CoreModules { public class WindModule : IWindModule { -// private static readonly log4net.ILog m_log -// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private int m_frame = 0; - private int m_frame_mod = 150; + private uint m_frame = 0; + private uint m_frameLastUpdateClientArray = 0; + private int m_frameUpdateRate = 150; private Random m_rndnums = new Random(Environment.TickCount); private Scene m_scene = null; private bool m_ready = false; - private float m_strength = 1.0F; + private bool m_enabled = true; + private IWindModelPlugin m_activeWindPlugin = null; + private const string m_dWindPluginName = "SimpleRandomWind"; + private Dictionary m_availableWindPlugins = new Dictionary(); + // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m private Vector2[] windSpeeds = new Vector2[16 * 16]; - private Dictionary m_rootAgents = new Dictionary(); - + #region IRegion Methods + public void Initialise(Scene scene, IConfigSource config) { IConfig windConfig = config.Configs["Wind"]; + string desiredWindPlugin = m_dWindPluginName; if (windConfig != null) { m_enabled = windConfig.GetBoolean("enabled", true); - m_strength = windConfig.GetFloat("strength", 1.0F); + + m_frameUpdateRate = windConfig.GetInt("wind_update_rate", 150); + + // Determine which wind model plugin is desired + if (windConfig.Contains("wind_plugin")) + { + desiredWindPlugin = windConfig.GetString("wind_plugin"); + } } if (m_enabled) { + m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate); m_scene = scene; m_frame = 0; + // Register all the Wind Model Plug-ins + foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule")) + { + m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name); + m_availableWindPlugins.Add(windPlugin.Name, windPlugin); + } + + // Check for desired plugin + if (m_availableWindPlugins.ContainsKey(desiredWindPlugin)) + { + m_activeWindPlugin = m_availableWindPlugins[desiredWindPlugin]; + + m_log.InfoFormat("[WIND] {0} plugin found, initializing.", desiredWindPlugin); + + if (windConfig != null) + { + m_activeWindPlugin.Initialise(); + m_activeWindPlugin.WindConfig(m_scene, windConfig); + } + } + + + // if the plug-in wasn't found, default to no wind. + if (m_activeWindPlugin == null) + { + m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", desiredWindPlugin); + m_log.ErrorFormat("[WIND] Defaulting to no wind."); + } - scene.EventManager.OnFrame += WindUpdate; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnClientClosed += ClientLoggedOut; - scene.RegisterModuleInterface(this); + // This one puts an entry in the main help screen + m_scene.AddCommand(this, String.Empty, "wind", "Usage: wind [value] - Get or Update Wind paramaters", null); + + // This one enables the ability to type just the base command without any parameters + m_scene.AddCommand(this, "wind", "", "", HandleConsoleCommand); + // Get a list of the parameters for each plugin + foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values) + { + m_scene.AddCommand(this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand); + m_scene.AddCommand(this, String.Format("wind base wind_update_rate"), "Change the wind update rate.", "", HandleConsoleBaseCommand); + + foreach (KeyValuePair kvp in windPlugin.WindParams()) + { + m_scene.AddCommand(this, String.Format("wind {0} {1}", windPlugin.Name, kvp.Key), String.Format("{0} : {1} - {2}", windPlugin.Name, kvp.Key, kvp.Value), "", HandleConsoleParamCommand); + } + } + + + // Register event handlers for when Avatars enter the region, and frame ticks + m_scene.EventManager.OnFrame += WindUpdate; + m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion; + + // Register the wind module + m_scene.RegisterModuleInterface(this); + + // Generate initial wind values GenWindPos(); + // Mark Module Ready for duty m_ready = true; } @@ -93,12 +161,19 @@ namespace OpenSim.Region.CoreModules if (m_enabled) { m_ready = false; + + // REVIEW: If a region module is closed, is there a possibility that it'll re-open/initialize ?? + m_activeWindPlugin = null; + foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values) + { + windPlugin.Dispose(); + } + + m_availableWindPlugins.Clear(); + // Remove our hooks m_scene.EventManager.OnFrame -= WindUpdate; - // m_scene.EventManager.OnNewClient -= SunToClient; - m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent; - m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - m_scene.EventManager.OnClientClosed -= ClientLoggedOut; + m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion; } } @@ -112,144 +187,279 @@ namespace OpenSim.Region.CoreModules get { return false; } } - /// - /// Retrieve the wind speed at the given region coordinate. This - /// implimentation ignores Z. - /// - /// 0...255 - /// 0...255 - /// - public Vector3 WindSpeed(int x, int y, int z) - { - Vector3 windVector = new Vector3(0.0f, 0.0f, 0.0f); - - x /= 16; - y /= 16; - if (x < 0) x = 0; - if (x > 15) x = 15; - if (y < 0) y = 0; - if (y > 15) y = 15; - if (windSpeeds != null) + #endregion + + #region Console Commands + private void ValidateConsole() + { + if (m_scene.ConsoleScene() == null) { - windVector.X = windSpeeds[y * 16 + x].X; - windVector.Y = windSpeeds[y * 16 + x].Y; + // FIXME: If console region is root then this will be printed by every module. Currently, there is no + // way to prevent this, short of making the entire module shared (which is complete overkill). + // One possibility is to return a bool to signal whether the module has completely handled the command + m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters."); + return; } + if (m_scene.ConsoleScene() != m_scene) + { + m_log.InfoFormat("[WIND]: Console Scene is not my scene."); + return; + } + } - return windVector; + /// + /// Base console command handler, only used if a person specifies the base command with now options + /// + private void HandleConsoleCommand(string module, string[] cmdparams) + { + ValidateConsole(); + m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); } - public void WindToClient(IClientAPI client) + /// + /// Called to change the active wind model plugin + /// + private void HandleConsoleBaseCommand(string module, string[] cmdparams) { - if (m_ready) + ValidateConsole(); + + if( (cmdparams.Length != 4) + || !cmdparams[1].Equals("base") + ) { - //if (!sunFixed) - //GenWindPos(); // Generate shared values once - client.SendWindData(windSpeeds); + m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base "); + return; } + + switch (cmdparams[2]) + { + case "wind_update_rate": + int newRate = 1; + + if (int.TryParse(cmdparams[3], out newRate)) + { + m_frameUpdateRate = newRate; + } + else + { + m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); + return; + } + + break; + case "wind_plugin": + string desiredPlugin = cmdparams[3]; + + if (desiredPlugin.Equals(m_activeWindPlugin.Name)) + { + m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]); + return; + } + + if (m_availableWindPlugins.ContainsKey(desiredPlugin)) + { + m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]]; + m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name); + } + else + { + m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin); + } + break; + } + } - public void WindUpdate() + /// + /// Called to change plugin parameters. + /// + private void HandleConsoleParamCommand(string module, string[] cmdparams) { - if (((m_frame++ % m_frame_mod) != 0) || !m_ready) + ValidateConsole(); + + // wind [value] + if ((cmdparams.Length != 4) + && (cmdparams.Length != 3)) { + m_log.Info("[WIND] Usage: wind [value]"); return; } - //m_log.Debug("[WIND]:Regenerating..."); - GenWindPos(); // Generate shared values once - //int spotxp = 0; - //int spotyp = 0; - //int spotxm = 0; - //int spotym = 0; - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) + string plugin = cmdparams[1]; + string param = cmdparams[2]; + float value = 0f; + if (cmdparams.Length == 4) { - if (!avatar.IsChildAgent) + if (!float.TryParse(cmdparams[3], out value)) { - avatar.ControllingClient.SendWindData(windSpeeds); + m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]); } - } - // set estate settings for region access to sun position - //m_scene.RegionInfo.RegionSettings.SunVector = Position; - //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); - } - - public void ForceWindUpdateToAllClients() - { - GenWindPos(); // Generate shared values once - - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) + try + { + WindParamSet(plugin, param, value); + } + catch (Exception e) + { + m_log.InfoFormat("[WIND] {0}", e.Message); + } + } + else { - if (!avatar.IsChildAgent) - avatar.ControllingClient.SendWindData(windSpeeds); + try + { + value = WindParamGet(plugin, param); + m_log.InfoFormat("[WIND] {0} : {1}", param, value); + } + catch (Exception e) + { + m_log.InfoFormat("[WIND] {0}", e.Message); + } } - // set estate settings for region access to sun position - //m_scene.RegionInfo.RegionSettings.SunVector = Position; - //m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime(); } + #endregion + + + #region IWindModule Methods + /// - /// Calculate the sun's orbital position and its velocity. + /// Retrieve the wind speed at the given region coordinate. This + /// implimentation ignores Z. /// + /// 0...255 + /// 0...255 + public Vector3 WindSpeed(int x, int y, int z) + { + if (m_activeWindPlugin != null) + { + return m_activeWindPlugin.WindSpeed(x, y, z); + } + else + { + return new Vector3(0.0f, 0.0f, 0.0f); + } + } - private void GenWindPos() + public void WindParamSet(string plugin, string param, float value) { - for (int y = 0; y < 16; y++) + if (m_availableWindPlugins.ContainsKey(plugin)) { - for (int x = 0; x < 16; x++) - { - windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 - windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 - windSpeeds[y * 16 + x].X *= m_strength; - windSpeeds[y * 16 + x].Y *= m_strength; - } + IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; + windPlugin.WindParamSet(param, value); + m_log.InfoFormat("[WIND] {0} set to {1}", param, value); + } + else + { + throw new Exception(String.Format("Could not find plugin {0}", plugin)); } + } - private void ClientLoggedOut(UUID AgentId) + public float WindParamGet(string plugin, string param) { - lock (m_rootAgents) + if (m_availableWindPlugins.ContainsKey(plugin)) { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - } + IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; + return windPlugin.WindParamGet(param); + } + else + { + throw new Exception(String.Format("Could not find plugin {0}", plugin)); } } - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) + public string WindActiveModelPluginName { - lock (m_rootAgents) + get { - if (m_rootAgents.ContainsKey(avatar.UUID)) + if (m_activeWindPlugin != null) { - m_rootAgents[avatar.UUID] = avatar.RegionHandle; + return m_activeWindPlugin.Name; } else { - m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); - WindToClient(avatar.ControllingClient); + return String.Empty; } } - //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); } - private void MakeChildAgent(ScenePresence avatar) + #endregion + + /// + /// Called on each frame update. Updates the wind model and clients as necessary. + /// + public void WindUpdate() + { + if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready) + { + return; + } + + GenWindPos(); + + SendWindAllClients(); + } + + public void OnAgentEnteredRegion(ScenePresence avatar) + { + if (m_ready) + { + if (m_activeWindPlugin != null) + { + // Ask wind plugin to generate a LL wind array to be cached locally + // Try not to update this too often, as it may involve array copies + if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate)) + { + windSpeeds = m_activeWindPlugin.WindLLClientArray(); + m_frameLastUpdateClientArray = m_frame; + } + } + + avatar.ControllingClient.SendWindData(windSpeeds); + } + } + + private void SendWindAllClients() { - lock (m_rootAgents) + if (m_ready) { - if (m_rootAgents.ContainsKey(avatar.UUID)) + List avatars = m_scene.GetAvatars(); + + if (avatars.Count > 0) { - if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) + // Ask wind plugin to generate a LL wind array to be cached locally + // Try not to update this too often, as it may involve array copies + if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate)) + { + windSpeeds = m_activeWindPlugin.WindLLClientArray(); + m_frameLastUpdateClientArray = m_frame; + } + + foreach (ScenePresence avatar in avatars) { - m_rootAgents.Remove(avatar.UUID); + if (!avatar.IsChildAgent) + avatar.ControllingClient.SendWindData(windSpeeds); } } } } + /// + /// Calculate the sun's orbital position and its velocity. + /// + + private void GenWindPos() + { + if( m_activeWindPlugin != null ) + { + // Tell Wind Plugin to update it's wind data + m_activeWindPlugin.WindUpdate(m_frame); + } + } + + + } } diff --git a/OpenSim/Region/Framework/Interfaces/IWindModule.cs b/OpenSim/Region/Framework/Interfaces/IWindModule.cs index 84effd0..fe5d3ac 100644 --- a/OpenSim/Region/Framework/Interfaces/IWindModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IWindModule.cs @@ -36,5 +36,20 @@ namespace OpenSim.Region.Framework.Interfaces /// Retrieves the current wind speed at the given Region Coordinates /// Vector3 WindSpeed(int x, int y, int z); + + /// + /// Set Wind Plugin Parameter + /// + void WindParamSet(string plugin, string param, float value); + + /// + /// Get Wind Plugin Parameter + /// + float WindParamGet(string plugin, string param); + + /// + /// Current active wind model plugin or String.Empty + /// + string WindActiveModelPluginName { get; } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index c87cc44..491a971 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -268,7 +268,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // // OpenSim functions // - public int osTerrainSetHeight(int x, int y, double val) { CheckThreatLevel(ThreatLevel.High, "osTerrainSetHeight"); @@ -920,6 +919,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } + public string osWindActiveModelPluginName() + { + CheckThreatLevel(ThreatLevel.None, "osWindActiveModelPluginName"); + m_host.AddScriptLPS(1); + + IWindModule module = World.RequestModuleInterface(); + if (module != null) + { + return module.WindActiveModelPluginName; + } + + return String.Empty; + } + + public void osWindParamSet(string plugin, string param, float value) + { + CheckThreatLevel(ThreatLevel.VeryLow, "osWindParamSet"); + m_host.AddScriptLPS(1); + + IWindModule module = World.RequestModuleInterface(); + if (module != null) + { + try + { + module.WindParamSet(plugin, param, value); + } + catch (Exception) { } + } + } + + public float osWindParamGet(string plugin, string param) + { + CheckThreatLevel(ThreatLevel.VeryLow, "osWindParamGet"); + m_host.AddScriptLPS(1); + + IWindModule module = World.RequestModuleInterface(); + if (module != null) + { + return module.WindParamGet(plugin, param); + } + + return 0.0f; + } + public double osList2Double(LSL_Types.list src, int index) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index a2a0fea..533ed27 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -104,6 +104,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces double osSunGetParam(string param); void osSunSetParam(string param, double value); + // Wind Module Functions + string osWindActiveModelPluginName(); + void osWindParamSet(string plugin, string param, float value); + float osWindParamGet(string plugin, string param); + string osGetScriptEngineName(); string osGetSimulatorVersion(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index fa45836..54ae32a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -87,6 +87,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osSunSetParam(param, value); } + public string osWindActiveModelPluginName() + { + return m_OSSL_Functions.osWindActiveModelPluginName(); + } + + void osWindParamSet(string plugin, string param, float value) + { + m_OSSL_Functions.osWindParamSet(plugin, param, value); + } + + float osWindParamGet(string plugin, string param) + { + return m_OSSL_Functions.osWindParamGet(plugin, param); + } + + public double osList2Double(LSL_Types.list src, int index) { diff --git a/bin/OpenSim.addin.xml b/bin/OpenSim.addin.xml index 82adfa6..e026e24 100644 --- a/bin/OpenSim.addin.xml +++ b/bin/OpenSim.addin.xml @@ -12,4 +12,7 @@ + + + diff --git a/prebuild.xml b/prebuild.xml index 51f7cfa..3acb6d4 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1166,11 +1166,15 @@ + + + + - + @@ -3214,3 +3218,4 @@ + -- cgit v1.1