refactored command parsing
parent
60cb5a018c
commit
99bc21499b
|
@ -136,7 +136,7 @@ namespace Flocking
|
||||||
m_acc += sep;
|
m_acc += sep;
|
||||||
m_acc += ali;
|
m_acc += ali;
|
||||||
m_acc += coh;
|
m_acc += coh;
|
||||||
m_acc += ori;
|
//m_acc += ori;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, https://github.com/jonc/osboids
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (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 log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace Flocking
|
||||||
|
{
|
||||||
|
public abstract class FlockingCommand
|
||||||
|
{
|
||||||
|
protected static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType);
|
||||||
|
protected FlockingController m_controller;
|
||||||
|
protected string m_name;
|
||||||
|
protected string m_args;
|
||||||
|
protected string m_description;
|
||||||
|
|
||||||
|
public FlockingCommand( string name, string args, string description ) {
|
||||||
|
m_name = name;
|
||||||
|
m_args = args;
|
||||||
|
m_description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle (string module, string[] args) {
|
||||||
|
if( ShouldHandleCmd() ) {
|
||||||
|
Invoke( args );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ShouldHandleCmd ()
|
||||||
|
{
|
||||||
|
return View.Scene.ConsoleScene () == View.Scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Invoke( string[] args );
|
||||||
|
|
||||||
|
public string Name {
|
||||||
|
get{ return m_name;}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Params {
|
||||||
|
get{ return m_args; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Description {
|
||||||
|
get{ return m_description;}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlockingController Controller {
|
||||||
|
get{ return m_controller; }
|
||||||
|
set{ m_controller = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlockingModel Model {
|
||||||
|
get { return Controller.Model; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlockingView View {
|
||||||
|
get { return Controller.View; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoostCommand : FlockingCommand {
|
||||||
|
|
||||||
|
public RoostCommand() : base( "roost", "", "return all the boids to the start position and remove them from the scene") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args) {
|
||||||
|
if( Model.Active ) {
|
||||||
|
Model.Goal = FlockGoal.Roost;
|
||||||
|
} else {
|
||||||
|
Controller.ShowResponse ("Flock is not active, roost has no effect", args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StopCommand : FlockingCommand {
|
||||||
|
|
||||||
|
public StopCommand() : base("stop", "", "stop all Flocking"){}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args) {
|
||||||
|
m_log.Info ("stopping the flocking activity");
|
||||||
|
Model.Active = false;
|
||||||
|
View.Clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetPositionCommand : FlockingCommand {
|
||||||
|
public SetPositionCommand() : base("position", "x,y,z", "location that the boids will start flocking from") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
float x = Convert.ToSingle (args [1]);
|
||||||
|
float y = Convert.ToSingle (args [2]);
|
||||||
|
float z = Convert.ToSingle (args [3]);
|
||||||
|
Vector3 startPos = new Vector3 (x, y, z);
|
||||||
|
if (Model.ContainsPoint (startPos)) {
|
||||||
|
Model.StartPosition = startPos;
|
||||||
|
} else {
|
||||||
|
Controller.ShowResponse (startPos + "is not within the flow field", args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetParameterCommand : FlockingCommand {
|
||||||
|
public SetParameterCommand() : base("set", "name, value", "change the flock behaviour properties"){}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
string name = args [1];
|
||||||
|
string newVal = args [2];
|
||||||
|
|
||||||
|
BoidBehaviour behaviour = Model.Behaviour;
|
||||||
|
|
||||||
|
if (behaviour.IsValidParameter (name)) {
|
||||||
|
behaviour.SetParameter (name, newVal);
|
||||||
|
} else {
|
||||||
|
Controller.ShowResponse (name + "is not a valid flock parameter", args);
|
||||||
|
Controller.ShowResponse ("valid parameters are: " + behaviour.GetList (), args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetFrameRateCommand : FlockingCommand {
|
||||||
|
public SetFrameRateCommand() : base("framerate", "num", "[debugging] only update boids every <num> frames") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
int frameRate = Convert.ToInt32 (args [1]);
|
||||||
|
Controller.FrameUpdateRate = frameRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetBoundsCommand : FlockingCommand {
|
||||||
|
public SetBoundsCommand() : base("bounds", "xMin,xMax,yMin,yMax,zMin,zMax", "Bounds of the 3D space that the flock will be confined to") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
//TODO:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetSizeCommand : FlockingCommand {
|
||||||
|
public SetSizeCommand() : base("size", "num", "Adjust the size of the flock ") {}
|
||||||
|
|
||||||
|
public override void Invoke (string [] args)
|
||||||
|
{
|
||||||
|
lock (Controller.UI_SYNC) {
|
||||||
|
int newSize = Convert.ToInt32 (args [1]);
|
||||||
|
Model.Size = newSize;
|
||||||
|
View.Clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetPrimCommand : FlockingCommand {
|
||||||
|
public SetPrimCommand() : base("prim", "name", "set the prim used for each boid to that passed in") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
string primName = args [1];
|
||||||
|
lock (Controller.UI_SYNC) {
|
||||||
|
View.BoidPrim = primName;
|
||||||
|
View.Clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShowStatsCommand : FlockingCommand {
|
||||||
|
public ShowStatsCommand() : base("stats", "", "show flocking stats") {}
|
||||||
|
|
||||||
|
public override void Invoke (string[] args)
|
||||||
|
{
|
||||||
|
string str = Model.ToString ();
|
||||||
|
Controller.ShowResponse (str, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StartCommand : FlockingCommand {
|
||||||
|
public StartCommand() : base("start", "", "Start Flocking") {}
|
||||||
|
|
||||||
|
public override void Invoke(string[] args) {
|
||||||
|
if( Model.Active ) {
|
||||||
|
Controller.ShowResponse("Already active, restarting", args);
|
||||||
|
Model.Active = false;
|
||||||
|
View.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.Info ("start the flocking capability");
|
||||||
|
Model.Goal = FlockGoal.Flock;
|
||||||
|
Controller.Start ();
|
||||||
|
Model.Active = true;
|
||||||
|
//m_module.FlockUpdate ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,31 +63,86 @@ namespace Flocking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FlockingCommandParser
|
public class FlockingController
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType);
|
||||||
private IRegionModuleBase m_module;
|
public object UI_SYNC = new object ();
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
private FlockingModel m_model;
|
||||||
|
private FlockingView m_view;
|
||||||
private int m_chatChannel;
|
private int m_chatChannel;
|
||||||
private UUID m_owner;
|
private UUID m_owner;
|
||||||
private Dictionary<string, BoidCmdDelegate> m_commandMap = new Dictionary<string, BoidCmdDelegate> ();
|
private Dictionary<string, BoidCmdDelegate> m_commandMap = new Dictionary<string, BoidCmdDelegate> ();
|
||||||
private Dictionary<string, BoidCmdDefn> m_syntaxMap = new Dictionary<string, BoidCmdDefn> ();
|
private Dictionary<string, BoidCmdDefn> m_syntaxMap = new Dictionary<string, BoidCmdDefn> ();
|
||||||
|
private uint m_frame = 0;
|
||||||
|
private int m_frameUpdateRate = 1;
|
||||||
|
private Vector3 m_startPos = new Vector3 (128f, 128f, 128f);
|
||||||
|
private int m_minX = 0;
|
||||||
|
private int m_maxX = 256;
|
||||||
|
private int m_minY = 0;
|
||||||
|
private int m_maxY = 256;
|
||||||
|
private int m_minZ = 0;
|
||||||
|
private int m_maxZ = 256;
|
||||||
|
|
||||||
|
|
||||||
public FlockingCommandParser (IRegionModuleBase module, Scene scene, int channel)
|
|
||||||
|
public FlockingController (Scene scene, BoidBehaviour behaviour, int channel, string prim, int flockSize)
|
||||||
{
|
{
|
||||||
m_module = module;
|
//make the view
|
||||||
|
// who is the owner for the flock in this region
|
||||||
|
UUID owner = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||||
|
m_view = new FlockingView (scene);
|
||||||
|
m_view.PostInitialize (owner);
|
||||||
|
m_view.BoidPrim = prim;
|
||||||
|
|
||||||
|
//make the model
|
||||||
|
FlowField field = new FlowField( scene, m_minX, m_maxX, m_minY, m_maxY, m_minZ, m_maxZ);
|
||||||
|
FlockingModel model = new FlockingModel(field, behaviour, m_startPos);
|
||||||
|
Vector3 startPos = new Vector3(128f, 128f, 128f);//scene.GetSceneObjectPart (View.BoidPrim).ParentGroup.AbsolutePosition;
|
||||||
|
model.StartPosition = startPos; // TODO: by default start from the prim
|
||||||
|
|
||||||
|
m_model = model;
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_chatChannel = channel;
|
m_chatChannel = channel;
|
||||||
|
|
||||||
// who do we respond to in send messages
|
// who do we respond to in send messages
|
||||||
m_owner = scene.RegionInfo.EstateSettings.EstateOwner;
|
m_owner = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||||
|
|
||||||
// register our event handlers
|
// register our event handlers
|
||||||
|
m_scene.EventManager.OnFrame += FlockUpdate; // plug in to the game loop
|
||||||
m_scene.EventManager.OnChatFromClient += ProcessChatCommand; //listen for commands sent from the client
|
m_scene.EventManager.OnChatFromClient += ProcessChatCommand; //listen for commands sent from the client
|
||||||
|
IScriptModuleComms commsMod = m_scene.RequestModuleInterface<IScriptModuleComms>();
|
||||||
|
commsMod.OnScriptCommand += ProcessScriptCommand; // listen to scripts
|
||||||
|
}
|
||||||
|
|
||||||
IScriptModuleComms commsMod = scene.RequestModuleInterface<IScriptModuleComms>();
|
public void Start()
|
||||||
commsMod.OnScriptCommand += ProcessScriptCommand;
|
{
|
||||||
|
//ask the view how big the boid prim is
|
||||||
|
Vector3 scale = View.GetBoidSize ();
|
||||||
|
|
||||||
|
FlowField field = new FlowField( m_scene, m_minX, m_maxX, m_minY, m_maxY, m_minZ, m_maxZ);
|
||||||
|
// init model
|
||||||
|
m_log.Info ("creating model");
|
||||||
|
// Generate initial flock values
|
||||||
|
m_model.BoidSize = scale;
|
||||||
|
m_model.Initialise (field);
|
||||||
|
m_log.Info ("done");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int FrameUpdateRate {
|
||||||
|
get { return m_frameUpdateRate; }
|
||||||
|
set { m_frameUpdateRate = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlockingModel Model {
|
||||||
|
get { return m_model; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlockingView View {
|
||||||
|
get { return m_view; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deregister ()
|
public void Deregister ()
|
||||||
|
@ -95,26 +150,48 @@ namespace Flocking
|
||||||
m_scene.EventManager.OnChatFromClient -= ProcessChatCommand;
|
m_scene.EventManager.OnChatFromClient -= ProcessChatCommand;
|
||||||
IScriptModuleComms commsMod = m_scene.RequestModuleInterface<IScriptModuleComms>();
|
IScriptModuleComms commsMod = m_scene.RequestModuleInterface<IScriptModuleComms>();
|
||||||
commsMod.OnScriptCommand -= ProcessScriptCommand;
|
commsMod.OnScriptCommand -= ProcessScriptCommand;
|
||||||
|
m_scene.EventManager.OnFrame -= FlockUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCommand (string cmd, string args, string help, CommandDelegate fn)
|
public void AddCommand (IRegionModuleBase module, FlockingCommand cmd)
|
||||||
{
|
{
|
||||||
|
cmd.Controller = this;
|
||||||
|
string name = cmd.Name;
|
||||||
|
string args = cmd.Params;
|
||||||
|
string help = cmd.Description;
|
||||||
|
CommandDelegate fn =cmd.Handle;
|
||||||
|
|
||||||
string argStr = "";
|
string argStr = "";
|
||||||
if (args.Trim ().Length > 0) {
|
if (args.Trim ().Length > 0) {
|
||||||
argStr = " <" + args + "> ";
|
argStr = " <" + args + "> ";
|
||||||
}
|
}
|
||||||
m_commandMap.Add (cmd, new BoidCmdDelegate (fn));
|
m_commandMap.Add (name, new BoidCmdDelegate (fn));
|
||||||
m_syntaxMap.Add (cmd, new BoidCmdDefn (cmd, args, help));
|
m_syntaxMap.Add (name, new BoidCmdDefn (name, args, help));
|
||||||
// register this command with the console
|
// register this command with the console
|
||||||
m_scene.AddCommand (m_module, "flock-" + cmd, "flock-" + cmd + argStr, help, fn);
|
m_scene.AddCommand (module, "flock-" + name, "flock-" + name + argStr, help, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region handlers
|
#region handlers
|
||||||
|
|
||||||
|
public void FlockUpdate ()
|
||||||
|
{
|
||||||
|
if (((m_frame++ % m_frameUpdateRate) != 0) || !m_model.Active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// work out where everyone has moved to
|
||||||
|
// and tell the scene to render the new positions
|
||||||
|
lock (UI_SYNC) {
|
||||||
|
List<Boid > boids = m_model.UpdateFlockPos ();
|
||||||
|
m_view.Render (boids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void ProcessScriptCommand (UUID scriptId, string reqId, string module, string input, string key)
|
public void ProcessScriptCommand (UUID scriptId, string reqId, string module, string input, string key)
|
||||||
{
|
{
|
||||||
if (m_module.Name != module) {
|
if (FlockingModule.NAME != module) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +250,7 @@ namespace Flocking
|
||||||
// we got the signature of the command right
|
// we got the signature of the command right
|
||||||
BoidCmdDelegate del = null;
|
BoidCmdDelegate del = null;
|
||||||
if (m_commandMap.TryGetValue (args [0], out del)) {
|
if (m_commandMap.TryGetValue (args [0], out del)) {
|
||||||
del (m_module.Name, args);
|
del (FlockingModule.NAME, args);
|
||||||
} else {
|
} else {
|
||||||
// we don't understand this command
|
// we don't understand this command
|
||||||
// shouldn't happen
|
// shouldn't happen
|
|
@ -31,15 +31,30 @@ using Utils = OpenSim.Framework.Util;
|
||||||
|
|
||||||
namespace Flocking
|
namespace Flocking
|
||||||
{
|
{
|
||||||
|
public enum FlockGoal
|
||||||
|
{
|
||||||
|
Roost = 0x01,
|
||||||
|
Perch = 0x02,
|
||||||
|
Flock = 0x04,
|
||||||
|
}
|
||||||
|
|
||||||
public class FlockingModel
|
public class FlockingModel
|
||||||
{
|
{
|
||||||
private List<Boid> m_flock = new List<Boid>();
|
private List<Boid> m_flock = new List<Boid>();
|
||||||
private FlowField m_flowField;
|
private FlowField m_flowField;
|
||||||
private BoidBehaviour m_behaviour;
|
private BoidBehaviour m_behaviour;
|
||||||
private Random m_rnd = new Random(Environment.TickCount);
|
private int m_flockSize = 100;
|
||||||
private int m_flockSize;
|
|
||||||
private Vector3 m_boidSize;
|
private Vector3 m_boidSize;
|
||||||
private Vector3 m_startPos;
|
private Vector3 m_startPos;
|
||||||
|
private FlockGoal m_goal = FlockGoal.Flock;
|
||||||
|
private bool m_active = false;
|
||||||
|
private int m_minX = 0;
|
||||||
|
private int m_maxX = 256;
|
||||||
|
private int m_minY = 0;
|
||||||
|
private int m_maxY = 256;
|
||||||
|
private int m_minZ = 0;
|
||||||
|
private int m_maxZ = 256;
|
||||||
|
|
||||||
|
|
||||||
public int Size {
|
public int Size {
|
||||||
get {return m_flockSize;}
|
get {return m_flockSize;}
|
||||||
|
@ -52,7 +67,86 @@ namespace Flocking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlockingModel( BoidBehaviour behaviour, Vector3 startPos ) {
|
public FlockGoal Goal {
|
||||||
|
get { return m_goal; }
|
||||||
|
set { m_goal = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxX {
|
||||||
|
get {
|
||||||
|
return this.m_maxX;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_maxX = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxY {
|
||||||
|
get {
|
||||||
|
return this.m_maxY;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_maxY = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxZ {
|
||||||
|
get {
|
||||||
|
return this.m_maxZ;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_maxZ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinX {
|
||||||
|
get {
|
||||||
|
return this.m_minX;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_minX = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinY {
|
||||||
|
get {
|
||||||
|
return this.m_minY;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_minY = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinZ {
|
||||||
|
get {
|
||||||
|
return this.m_minZ;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
m_minZ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool Active {
|
||||||
|
get { return m_active; }
|
||||||
|
set { m_active = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 StartPosition {
|
||||||
|
get { return m_startPos; }
|
||||||
|
set { m_startPos = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoidBehaviour Behaviour {
|
||||||
|
get { return m_behaviour; }
|
||||||
|
set { m_behaviour = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 BoidSize {
|
||||||
|
set { m_boidSize = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FlockingModel( FlowField field, BoidBehaviour behaviour, Vector3 startPos ) {
|
||||||
|
m_flowField = field;
|
||||||
m_behaviour = behaviour;
|
m_behaviour = behaviour;
|
||||||
m_startPos = startPos;
|
m_startPos = startPos;
|
||||||
}
|
}
|
||||||
|
@ -60,21 +154,26 @@ namespace Flocking
|
||||||
void AddBoid (string name)
|
void AddBoid (string name)
|
||||||
{
|
{
|
||||||
Boid boid = new Boid (name, m_boidSize, m_behaviour);
|
Boid boid = new Boid (name, m_boidSize, m_behaviour);
|
||||||
|
double d1 = ( Utils.RandomClass.NextDouble() - 0.5 ) * 20;
|
||||||
boid.Location = m_startPos;
|
double d2 = ( Utils.RandomClass.NextDouble() - 0.5 ) * 20;
|
||||||
|
double d3 = ( Utils.RandomClass.NextDouble() - 0.5 ) * 20;
|
||||||
|
boid.Location = m_startPos + new Vector3( (float)d1, (float)d2, (float)d3 );
|
||||||
boid.Velocity = Vector3.UnitX;
|
boid.Velocity = Vector3.UnitX;
|
||||||
m_flock.Add (boid);
|
m_flock.Add (boid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsPoint (Vector3 position)
|
||||||
|
{
|
||||||
|
return m_flowField.ContainsPoint( position );
|
||||||
|
}
|
||||||
|
|
||||||
public void Initialise (int flockSize, Vector3 boidSize, FlowField flowField)
|
|
||||||
|
public void Initialise (FlowField flowField)
|
||||||
{
|
{
|
||||||
m_flowField = flowField;
|
m_flowField = flowField;
|
||||||
m_flockSize = flockSize;
|
|
||||||
m_boidSize = boidSize;
|
|
||||||
for (int i = 0; i < m_flockSize; i++) {
|
for (int i = 0; i < m_flockSize; i++) {
|
||||||
AddBoid ("boid"+i );
|
AddBoid ("boid"+i );
|
||||||
UpdateFlockPos();
|
//UpdateFlockPos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +187,11 @@ namespace Flocking
|
||||||
|
|
||||||
public List<Boid> UpdateFlockPos ()
|
public List<Boid> UpdateFlockPos ()
|
||||||
{
|
{
|
||||||
|
if( m_active ) {
|
||||||
m_flock.ForEach( delegate(Boid boid) {
|
m_flock.ForEach( delegate(Boid boid) {
|
||||||
boid.MoveInSceneRelativeToFlock(GetNeighbours(boid), m_flowField);
|
boid.MoveInSceneRelativeToFlock(GetNeighbours(boid), m_flowField);
|
||||||
} );
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
return m_flock;
|
return m_flock;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +200,8 @@ namespace Flocking
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
string retVal = "Num Boids: " + m_flockSize + Environment.NewLine
|
string retVal = "Num Boids: " + m_flockSize + Environment.NewLine
|
||||||
+ m_behaviour.ToString();
|
+ m_behaviour.ToString() + Environment.NewLine
|
||||||
|
+ m_flowField.ToString();
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,54 +38,42 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
|
||||||
namespace Flocking
|
namespace Flocking
|
||||||
{
|
{
|
||||||
public class FlockingModule : INonSharedRegionModule
|
public class FlockingModule : INonSharedRegionModule
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType);
|
public static string NAME = "FlockingModule";
|
||||||
static object m_sync = new object();
|
|
||||||
|
|
||||||
private Scene m_scene;
|
|
||||||
private FlockingModel m_model;
|
|
||||||
private FlockingView m_view;
|
|
||||||
private bool m_enabled = false;
|
private bool m_enabled = false;
|
||||||
private bool m_active = false;
|
|
||||||
private uint m_frame = 0;
|
|
||||||
private int m_frameUpdateRate = 1;
|
|
||||||
private int m_chatChannel = 118;
|
private int m_chatChannel = 118;
|
||||||
private string m_boidPrim = "boid-prim";
|
private string m_boidPrim = "boid-prim";
|
||||||
private FlockingCommandParser m_commandParser;
|
private FlockingController m_controller;
|
||||||
private BoidBehaviour m_behaviour;
|
private BoidBehaviour m_behaviour;
|
||||||
private int m_flockSize = 100;
|
private int m_flockSize = 100;
|
||||||
|
|
||||||
private UUID m_owner;
|
|
||||||
|
|
||||||
#region IRegionModule Members
|
#region IRegionModule Members
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void Initialise (IConfigSource source)
|
public void Initialise (IConfigSource source)
|
||||||
{
|
{
|
||||||
//check if we are in the ini files
|
//check if we are in the ini files
|
||||||
//if so get some physical constants out of them and pass into the model
|
//if so get some default values out of them and pass them onto the controller
|
||||||
IConfig config = source.Configs ["Boids"];
|
IConfig config = source.Configs ["Boids"];
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
m_chatChannel = config.GetInt ("chat-channel", 118);
|
m_chatChannel = config.GetInt ("chat-channel", 118);
|
||||||
m_boidPrim = config.GetString ("boid-prim", "boidPrim");
|
m_boidPrim = config.GetString ("boid-prim", "boidPrim");
|
||||||
m_flockSize = config.GetInt ("flock-size", 100);
|
m_flockSize = config.GetInt ("flock-size", 100);
|
||||||
|
|
||||||
m_behaviour = new BoidBehaviour();
|
m_behaviour = new BoidBehaviour ();
|
||||||
m_behaviour.maxSpeed = config.GetFloat("max-speed", 3f);
|
m_behaviour.maxSpeed = config.GetFloat ("max-speed", 1f);
|
||||||
m_behaviour.maxForce = config.GetFloat("max-force", 0.25f);
|
m_behaviour.maxForce = config.GetFloat ("max-force", 0.25f);
|
||||||
m_behaviour.neighbourDistance = config.GetFloat("neighbour-dist", 25f);
|
m_behaviour.neighbourDistance = config.GetFloat ("neighbour-dist", 25f);
|
||||||
m_behaviour.desiredSeparation = config.GetFloat("desired-separation", 20f);
|
m_behaviour.desiredSeparation = config.GetFloat ("desired-separation", 20f);
|
||||||
m_behaviour.tolerance = config.GetFloat("tolerance", 5f);
|
m_behaviour.tolerance = config.GetFloat ("tolerance", 5f);
|
||||||
m_behaviour.separationWeighting = config.GetFloat("separation-weighting", 1.5f);
|
m_behaviour.separationWeighting = config.GetFloat ("separation-weighting", 1.5f);
|
||||||
m_behaviour.alignmentWeighting = config.GetFloat("alignment-weighting", 1f);
|
m_behaviour.alignmentWeighting = config.GetFloat ("alignment-weighting", 1f);
|
||||||
m_behaviour.cohesionWeighting = config.GetFloat("cohesion-weighting", 1f);
|
m_behaviour.cohesionWeighting = config.GetFloat ("cohesion-weighting", 1f);
|
||||||
m_behaviour.lookaheadDistance = config.GetFloat("lookahead-dist", 100f);
|
m_behaviour.lookaheadDistance = config.GetFloat ("lookahead-dist", 100f);
|
||||||
|
|
||||||
// we're in the config - so turn on this module
|
// we're in the config - so turn on this module
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
|
@ -94,42 +82,42 @@ namespace Flocking
|
||||||
|
|
||||||
public void AddRegion (Scene scene)
|
public void AddRegion (Scene scene)
|
||||||
{
|
{
|
||||||
//m_log.Info ("ADDING FLOCKING");
|
|
||||||
m_scene = scene;
|
|
||||||
if (m_enabled) {
|
|
||||||
|
|
||||||
//register handlers
|
|
||||||
m_scene.EventManager.OnFrame += FlockUpdate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegionLoaded (Scene scene)
|
public void RegionLoaded (Scene scene)
|
||||||
{
|
{
|
||||||
if (m_enabled) {
|
if (m_enabled) {
|
||||||
// who is the owner for the flock in this region
|
//set up the boid module
|
||||||
m_owner = scene.RegionInfo.EstateSettings.EstateOwner;
|
m_controller = new FlockingController (scene, m_behaviour, m_chatChannel, m_boidPrim, m_flockSize);
|
||||||
|
RegisterCommand (new RoostCommand());
|
||||||
//register command handler
|
RegisterCommand (new StopCommand());
|
||||||
m_commandParser = new FlockingCommandParser(this, scene, m_chatChannel);
|
RegisterCommand (new StartCommand());
|
||||||
RegisterCommands ();
|
RegisterCommand (new SetSizeCommand());
|
||||||
|
RegisterCommand (new ShowStatsCommand());
|
||||||
// init view
|
RegisterCommand (new SetPrimCommand());
|
||||||
m_view = new FlockingView (scene);
|
RegisterCommand (new SetPositionCommand());
|
||||||
m_view.PostInitialize (m_owner);
|
RegisterCommand (new SetBoundsCommand());
|
||||||
m_view.BoidPrim = m_boidPrim;
|
RegisterCommand (new SetFrameRateCommand());
|
||||||
|
RegisterCommand (new SetParameterCommand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RegisterCommand (FlockingCommand cmd)
|
||||||
|
{
|
||||||
|
m_controller.AddCommand( this, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void RemoveRegion (Scene scene)
|
public void RemoveRegion (Scene scene)
|
||||||
{
|
{
|
||||||
if (m_enabled) {
|
if (m_enabled) {
|
||||||
m_scene.EventManager.OnFrame -= FlockUpdate;
|
m_controller.Deregister ();
|
||||||
m_commandParser.Deregister();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name {
|
public string Name {
|
||||||
get { return "FlockingModule"; }
|
get { return NAME; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule {
|
public bool IsSharedModule {
|
||||||
|
@ -138,141 +126,8 @@ namespace Flocking
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region EventHandlers
|
|
||||||
|
|
||||||
public void FlockUpdate ()
|
|
||||||
{
|
|
||||||
if (((m_frame++ % m_frameUpdateRate) != 0) || !m_active || !m_enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// work out where everyone has moved to
|
|
||||||
// and tell the scene to render the new positions
|
|
||||||
lock( m_sync ) {
|
|
||||||
List<Boid > boids = m_model.UpdateFlockPos ();
|
|
||||||
m_view.Render (boids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
private void BuildFlowField(Vector3 centre, int width, int depth, int height) {
|
|
||||||
m_log.Info("building flow field");
|
|
||||||
//build a flow field based on the scene
|
|
||||||
FlowField field = new FlowField(m_scene, centre, width, depth, height);
|
|
||||||
m_log.Info("built");
|
|
||||||
//ask the view how big the boid prim is
|
|
||||||
Vector3 scale = m_view.GetBoidSize();
|
|
||||||
|
|
||||||
Vector3 startPos = m_scene.GetSceneObjectPart(m_view.BoidPrim).ParentGroup.AbsolutePosition;
|
|
||||||
// init model
|
|
||||||
m_log.Info("creating model");
|
|
||||||
m_model = new FlockingModel (m_behaviour, startPos );
|
|
||||||
// Generate initial flock values
|
|
||||||
m_model.Initialise (m_flockSize, scale, field);
|
|
||||||
m_log.Info("done");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Command Handling
|
|
||||||
|
|
||||||
|
|
||||||
private void RegisterCommands ()
|
|
||||||
{
|
|
||||||
m_commandParser.AddCommand ("stop", "", "Stop all Flocking", HandleStopCmd);
|
|
||||||
m_commandParser.AddCommand ("start", "", "Start Flocking", HandleStartCmd);
|
|
||||||
m_commandParser.AddCommand ("size", "num", "Adjust the size of the flock ", HandleSetSizeCmd);
|
|
||||||
m_commandParser.AddCommand ("stats", "", "show flocking stats", HandleShowStatsCmd);
|
|
||||||
m_commandParser.AddCommand ("prim", "name", "set the prim used for each boid to that passed in", HandleSetPrimCmd);
|
|
||||||
m_commandParser.AddCommand ("framerate", "num", "[debugging] only update boids every <num> frames", HandleSetFrameRateCmd);
|
|
||||||
m_commandParser.AddCommand ("set", "name, value", "change the flock behaviour properties", HandleSetParameterCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ShouldHandleCmd ()
|
|
||||||
{
|
|
||||||
return m_scene.ConsoleScene () == m_scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleSetParameterCmd(string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
string name = args[1];
|
|
||||||
string newVal = args[2];
|
|
||||||
|
|
||||||
if( m_behaviour.IsValidParameter( name ) ) {
|
|
||||||
m_behaviour.SetParameter(name, newVal);
|
|
||||||
} else {
|
|
||||||
m_commandParser.ShowResponse( name + "is not a valid flock parameter", args );
|
|
||||||
m_commandParser.ShowResponse( "valid parameters are: " + m_behaviour.GetList(), args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleStopCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
m_log.Info ("stop the flocking capability");
|
|
||||||
m_active = false;
|
|
||||||
m_view.Clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleSetFrameRateCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
int frameRate = Convert.ToInt32( args[1] );
|
|
||||||
m_frameUpdateRate = frameRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleStartCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
m_log.Info ("start the flocking capability");
|
|
||||||
BuildFlowField(new Vector3(128f, 128f, 128f), 200, 200, 200);
|
|
||||||
m_active = true;
|
|
||||||
FlockUpdate ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleSetSizeCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
lock( m_sync ) {
|
|
||||||
int newSize = Convert.ToInt32(args[1]);
|
|
||||||
m_model.Size = newSize;
|
|
||||||
m_view.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleShowStatsCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
string str = m_model.ToString();
|
|
||||||
m_commandParser.ShowResponse (str, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleSetPrimCmd (string module, string[] args)
|
|
||||||
{
|
|
||||||
if (ShouldHandleCmd ()) {
|
|
||||||
string primName = args[1];
|
|
||||||
lock(m_sync) {
|
|
||||||
m_view.BoidPrim = primName;
|
|
||||||
m_view.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region IRegionModuleBase Members
|
#region IRegionModuleBase Members
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void Close ()
|
public void Close ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,11 @@ namespace Flocking
|
||||||
set{ m_boidPrim = value; }
|
set{ m_boidPrim = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Scene Scene {
|
||||||
|
get {return m_scene;}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Vector3 GetBoidSize ()
|
public Vector3 GetBoidSize ()
|
||||||
{
|
{
|
||||||
float offsetHeight;
|
float offsetHeight;
|
||||||
|
|
|
@ -63,16 +63,16 @@ namespace Flocking
|
||||||
/// Height.
|
/// Height.
|
||||||
/// </param>
|
/// </param>
|
||||||
///
|
///
|
||||||
public FlowField (Scene scene, Vector3 centre, int width, int depth, int height)
|
public FlowField (Scene scene, int minX, int maxX, int minY, int maxY, int minZ, int maxZ)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
|
|
||||||
m_startX = Math.Max (BUFFER, centre.X - width / 2f);
|
m_startX = Math.Max (BUFFER, minX);
|
||||||
m_startY = Math.Max (BUFFER, centre.Y - depth / 2f);
|
m_startY = Math.Max (BUFFER, minY);
|
||||||
m_startZ = Math.Max (BUFFER, centre.Z - height / 2f);
|
m_startZ = Math.Max (BUFFER, minZ);
|
||||||
m_endX = Math.Min (Util.SCENE_SIZE - BUFFER, centre.X + width / 2f);
|
m_endX = Math.Min (Util.SCENE_SIZE - BUFFER, maxX);
|
||||||
m_endY = Math.Min (Util.SCENE_SIZE - BUFFER, centre.Y + depth / 2f);
|
m_endY = Math.Min (Util.SCENE_SIZE - BUFFER, maxY);
|
||||||
m_endZ = Math.Min (Util.SCENE_SIZE - BUFFER, centre.Z + height / 2f);
|
m_endZ = Math.Min (Util.SCENE_SIZE - BUFFER, maxZ);
|
||||||
|
|
||||||
// build the flow field over the given bounds
|
// build the flow field over the given bounds
|
||||||
Initialize ();
|
Initialize ();
|
||||||
|
@ -142,6 +142,16 @@ namespace Flocking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsPoint (Vector3 p)
|
||||||
|
{
|
||||||
|
return p.X > m_startX &&
|
||||||
|
p.X < m_endX &&
|
||||||
|
p.Y > m_startY &&
|
||||||
|
p.Y < m_endY &&
|
||||||
|
p.Z > m_startZ &&
|
||||||
|
p.Z < m_endZ;
|
||||||
|
}
|
||||||
|
|
||||||
private bool inBounds (int x, int y, int z)
|
private bool inBounds (int x, int y, int z)
|
||||||
{
|
{
|
||||||
return x >= 0 && x < 256 && y >= 0 && y < 256 && z >= 0;
|
return x >= 0 && x < 256 && y >= 0 && y < 256 && z >= 0;
|
||||||
|
@ -238,6 +248,17 @@ namespace Flocking
|
||||||
{
|
{
|
||||||
return m_field [(int)loc.X, (int)loc.Y, (int)loc.Z];
|
return m_field [(int)loc.X, (int)loc.Y, (int)loc.Z];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
return string.Format ("[FlowField]" + Environment.NewLine +
|
||||||
|
"startX = {0}" + Environment.NewLine +
|
||||||
|
"endX = {1}" + Environment.NewLine +
|
||||||
|
"startY = {2}" + Environment.NewLine +
|
||||||
|
"endY = {3}" + Environment.NewLine +
|
||||||
|
"startZ = {4}" + Environment.NewLine +
|
||||||
|
"endZ = {5}", m_startX, m_endX, m_startY, m_endY, m_startZ, m_endZ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<Reference name="OpenSim.Framework.Communications" path="../../../bin/" />
|
<Reference name="OpenSim.Framework.Communications" path="../../../bin/" />
|
||||||
<Reference name="OpenSim.Region.Framework" path="../../../bin/" />
|
<Reference name="OpenSim.Region.Framework" path="../../../bin/" />
|
||||||
<Reference name="OpenSim.Framework.Console" path="../../../bin/" />
|
<Reference name="OpenSim.Framework.Console" path="../../../bin/" />
|
||||||
|
<Reference name="OpenSim.Services.Interfaces" path="../../../bin/" />
|
||||||
<Reference name="OpenMetaverseTypes" path="../../../bin/" />
|
<Reference name="OpenMetaverseTypes" path="../../../bin/" />
|
||||||
<Reference name="OpenMetaverse" path="../../../bin/" />
|
<Reference name="OpenMetaverse" path="../../../bin/" />
|
||||||
<Files>
|
<Files>
|
||||||
|
|
Loading…
Reference in New Issue