Merge branch 'master' into careminster

Conflicts:
	OpenSim/Data/MySQL/MySQLSimulationData.cs
	OpenSim/Data/MySQL/Resources/RegionStore.migrations
	OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
	OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
	OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
	OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
	OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
avinationmerge
Melanie 2013-10-04 20:03:12 +01:00
commit 75c68fa29e
85 changed files with 2998 additions and 873 deletions

View File

@ -87,6 +87,7 @@ what it is today.
* Garmin Kawaguichi
* Gerhard
* Godfrey
* Greg C.
* Grumly57
* GuduleLapointe
* Ewe Loon

View File

@ -351,7 +351,7 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs,
LinkNumber = @LinkNumber, MediaURL = @MediaURL, AttachedPosX = @AttachedPosX, AttachedPosY = @AttachedPosY, AttachedPosZ = @AttachedPosZ, DynAttrs = @DynAttrs,
PhysicsShapeType = @PhysicsShapeType, Density = @Density, GravityModifier = @GravityModifier, Friction = @Friction, Restitution = @Restitution
WHERE UUID = @UUID
END
@ -367,7 +367,7 @@ ELSE
PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs,
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, AttachedPosX, AttachedPosY, AttachedPosZ, DynAttrs,
PhysicsShapeType, Density, GravityModifier, Friction, Restitution
) VALUES (
@UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
@ -378,7 +378,7 @@ ELSE
@PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
@OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
@ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs,
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @AttachedPosX, @AttachedPosY, @AttachedPosZ, @DynAttrs,
@PhysicsShapeType, @Density, @GravityModifier, @Friction, @Restitution
)
END";
@ -1695,6 +1695,12 @@ VALUES
if (!(primRow["MediaURL"] is System.DBNull))
prim.MediaUrl = (string)primRow["MediaURL"];
if (!(primRow["AttachedPosX"] is System.DBNull))
prim.AttachedPos = new Vector3(
Convert.ToSingle(primRow["AttachedPosX"]),
Convert.ToSingle(primRow["AttachedPosY"]),
Convert.ToSingle(primRow["AttachedPosZ"]));
if (!(primRow["DynAttrs"] is System.DBNull))
prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
else
@ -2099,6 +2105,9 @@ VALUES
parameters.Add(_Database.CreateParameter("PassTouches", 0));
parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
parameters.Add(_Database.CreateParameter("AttachedPosX", prim.AttachedPos.X));
parameters.Add(_Database.CreateParameter("AttachedPosY", prim.AttachedPos.Y));
parameters.Add(_Database.CreateParameter("AttachedPosZ", prim.AttachedPos.Z));
if (prim.DynAttrs.CountNamespaces > 0)
parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));

View File

@ -1168,3 +1168,15 @@ ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
COMMIT
:VERSION 40 #---------------- Save Attachment info
BEGIN TRANSACTION
ALTER TABLE prims ADD AttachedPosX float(53) default 0.0;
ALTER TABLE prims ADD AttachedPosY float(53) default 0.0;
ALTER TABLE prims ADD AttachedPosZ float(53) default 0.0;
ALTER TABLE primshapes ADD LastAttachPoint int not null default 0;
COMMIT

View File

@ -174,7 +174,8 @@ namespace OpenSim.Data.MySQL
"CollisionSound, CollisionSoundVolume, " +
"PassTouches, " +
"PassCollisions, " +
"LinkNumber, MediaURL, KeyframeMotion, " +
"LinkNumber, MediaURL, KeyframeMotion, AttachedPosX, " +
"AttachedPosY, AttachedPosZ, " +
"PhysicsShapeType, Density, GravityModifier, " +
"Friction, Restitution, Vehicle, DynAttrs " +
") values (" + "?UUID, " +
@ -209,7 +210,8 @@ namespace OpenSim.Data.MySQL
"?ColorB, ?ColorA, ?ParticleSystem, " +
"?ClickAction, ?Material, ?CollisionSound, " +
"?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " +
"?LinkNumber, ?MediaURL, ?KeyframeMotion, " +
"?LinkNumber, ?MediaURL, ?KeyframeMotion, ?AttachedPosX, " +
"?AttachedPosY, ?AttachedPosZ, " +
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
"?Friction, ?Restitution, ?Vehicle, ?DynAttrs)";
@ -228,7 +230,7 @@ namespace OpenSim.Data.MySQL
"PathTaperX, PathTaperY, PathTwist, " +
"PathTwistBegin, ProfileBegin, ProfileEnd, " +
"ProfileCurve, ProfileHollow, Texture, " +
"ExtraParams, State, Media) " +
"ExtraParams, State, LastAttachPoint, Media) " +
"values (?UUID, " +
"?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
"?PCode, ?PathBegin, ?PathEnd, " +
@ -240,7 +242,7 @@ namespace OpenSim.Data.MySQL
"?PathTwistBegin, ?ProfileBegin, " +
"?ProfileEnd, ?ProfileCurve, " +
"?ProfileHollow, ?Texture, ?ExtraParams, " +
"?State, ?Media)";
"?State, ?LastAttachPoint, ?Media)";
FillShapeCommand(cmd, prim);
@ -1321,6 +1323,15 @@ namespace OpenSim.Data.MySQL
if (!(row["MediaURL"] is System.DBNull))
prim.MediaUrl = (string)row["MediaURL"];
if (!(row["AttachedPosX"] is System.DBNull))
{
prim.AttachedPos = new Vector3(
(float)(double)row["AttachedPosX"],
(float)(double)row["AttachedPosY"],
(float)(double)row["AttachedPosZ"]
);
}
if (!(row["DynAttrs"] is System.DBNull))
prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]);
else
@ -1719,6 +1730,12 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
if (prim.AttachedPos != null)
{
cmd.Parameters.AddWithValue("AttachedPosX", (double)prim.AttachedPos.X);
cmd.Parameters.AddWithValue("AttachedPosY", (double)prim.AttachedPos.Y);
cmd.Parameters.AddWithValue("AttachedPosZ", (double)prim.AttachedPos.Z);
}
if (prim.KeyframeMotion != null)
cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize());
@ -1932,6 +1949,7 @@ namespace OpenSim.Data.MySQL
s.ExtraParams = (byte[])row["ExtraParams"];
s.State = (byte)(int)row["State"];
s.LastAttachPoint = (byte)(int)row["LastAttachPoint"];
if (!(row["Media"] is System.DBNull))
s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
@ -1978,6 +1996,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("Texture", s.TextureEntry);
cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams);
cmd.Parameters.AddWithValue("State", s.State);
cmd.Parameters.AddWithValue("LastAttachPoint", s.LastAttachPoint);
cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
}

View File

@ -922,3 +922,20 @@ ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
COMMIT;
:VERSION 48 #---------------- Keyframes
BEGIN;
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
COMMIT;
:VERSION 49 #--------------------- Save attachment info
BEGIN;
ALTER TABLE prims ADD COLUMN AttachedPosX double default 0;
ALTER TABLE prims ADD COLUMN AttachedPosY double default 0;
ALTER TABLE prims ADD COLUMN AttachedPosZ double default 0;
ALTER TABLE primshapes ADD COLUMN LastAttachPoint int(4) not null default '0';
COMMIT;

View File

@ -600,3 +600,15 @@ BEGIN;
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
COMMIT;
:VERSION 30 #---------------- Save Attachment info
BEGIN;
ALTER TABLE prims ADD COLUMN AttachedPosX double default '0';
ALTER TABLE prims ADD COLUMN AttachedPosY double default '0';
ALTER TABLE prims ADD COLUMN AttachedPosZ double default '0';
ALTER TABLE primshapes ADD COLUMN LastAttachPoint int not null default '0';
COMMIT;

View File

@ -1236,6 +1236,10 @@ namespace OpenSim.Data.SQLite
createCol(prims, "MediaURL", typeof(String));
createCol(prims, "AttachedPosX", typeof(Double));
createCol(prims, "AttachedPosY", typeof(Double));
createCol(prims, "AttachedPosZ", typeof(Double));
createCol(prims, "DynAttrs", typeof(String));
createCol(prims, "PhysicsShapeType", typeof(Byte));
@ -1724,6 +1728,12 @@ namespace OpenSim.Data.SQLite
prim.MediaUrl = (string)row["MediaURL"];
}
prim.AttachedPos = new Vector3(
Convert.ToSingle(row["AttachedPosX"]),
Convert.ToSingle(row["AttachedPosY"]),
Convert.ToSingle(row["AttachedPosZ"])
);
if (!(row["DynAttrs"] is System.DBNull))
{
//m_log.DebugFormat("[SQLITE]: DynAttrs type [{0}]", row["DynAttrs"].GetType());
@ -2176,6 +2186,10 @@ namespace OpenSim.Data.SQLite
row["MediaURL"] = prim.MediaUrl;
row["AttachedPosX"] = prim.AttachedPos.X;
row["AttachedPosY"] = prim.AttachedPos.Y;
row["AttachedPosZ"] = prim.AttachedPos.Z;
if (prim.DynAttrs.CountNamespaces > 0)
row["DynAttrs"] = prim.DynAttrs.ToXml();
else
@ -2444,6 +2458,7 @@ namespace OpenSim.Data.SQLite
s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
s.State = Convert.ToByte(row["State"]);
s.LastAttachPoint = Convert.ToByte(row["LastAttachPoint"]);
byte[] textureEntry = (byte[])row["Texture"];
s.TextureEntry = textureEntry;
@ -2493,6 +2508,7 @@ namespace OpenSim.Data.SQLite
row["ProfileCurve"] = s.ProfileCurve;
row["ProfileHollow"] = s.ProfileHollow;
row["State"] = s.State;
row["LastAttachPoint"] = s.LastAttachPoint;
row["Texture"] = s.TextureEntry;
row["ExtraParams"] = s.ExtraParams;

View File

@ -86,24 +86,26 @@ namespace OpenSim.Framework
event restart OnRestart;
/// <summary>
/// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent
/// Add a new agent with an attached client. All agents except initial login clients will starts off as a child agent
/// - the later agent crossing will promote it to a root agent.
/// </summary>
/// <param name="client"></param>
/// <param name="type">The type of agent to add.</param>
/// <returns>
/// The scene agent if the new client was added or if an agent that already existed.</returns>
ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
/// <summary>
/// Remove the given client from the scene.
/// Tell a single agent to disconnect from the region.
/// </summary>
/// <param name="agentID"></param>
/// <param name="closeChildAgents">Close the neighbour child agents associated with this client.</param>
void RemoveClient(UUID agentID, bool closeChildAgents);
/// <param name="force">
/// Force the agent to close even if it might be in the middle of some other operation. You do not want to
/// force unless you are absolutely sure that the agent is dead and a normal close is not working.
/// </param>
bool CloseAgent(UUID agentID, bool force);
void Restart();
//RegionInfo OtherRegionUp(RegionInfo thisRegion);
string GetSimulatorVersion();

View File

@ -105,6 +105,7 @@ namespace OpenSim.Framework
private ushort _profileHollow;
private Vector3 _scale;
private byte _state;
private byte _lastattach;
private ProfileShape _profileShape;
private HollowShape _hollowShape;
@ -207,6 +208,7 @@ namespace OpenSim.Framework
PCode = (byte)prim.PrimData.PCode;
State = prim.PrimData.State;
LastAttachPoint = prim.PrimData.State;
PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
@ -583,6 +585,15 @@ namespace OpenSim.Framework
}
}
public byte LastAttachPoint {
get {
return _lastattach;
}
set {
_lastattach = value;
}
}
public ProfileShape ProfileShape {
get {
return _profileShape;

View File

@ -200,7 +200,7 @@ namespace OpenSim.Framework
set { m_ObjectBonus = value; }
}
private int m_Maturity = 1;
private int m_Maturity = 0;
public int Maturity
{

View File

@ -1057,7 +1057,21 @@ namespace OpenSim.Framework.Servers.HttpServer
}
response.ContentType = "text/xml";
responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
using (MemoryStream outs = new MemoryStream())
{
using (XmlTextWriter writer = new XmlTextWriter(outs, Encoding.UTF8))
{
writer.Formatting = Formatting.None;
XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
writer.Flush();
outs.Flush();
outs.Position = 0;
using (StreamReader sr = new StreamReader(outs))
{
responseString = sr.ReadToEnd();
}
}
}
}
else
{

View File

@ -203,10 +203,10 @@ namespace OpenSim
m_config.Source.Merge(envConfigSource);
}
ReadConfigSettings();
m_config.Source.ExpandKeyValues();
ReadConfigSettings();
return m_config;
}

View File

@ -237,27 +237,33 @@ namespace OpenSim
m_console.Commands.AddCommand("General", false, "change region",
"change region <region name>",
"Change current console region", ChangeSelectedRegion);
"Change current console region",
ChangeSelectedRegion);
m_console.Commands.AddCommand("Archiving", false, "save xml",
"save xml",
"Save a region's data in XML format", SaveXml);
"Save a region's data in XML format",
SaveXml);
m_console.Commands.AddCommand("Archiving", false, "save xml2",
"save xml2",
"Save a region's data in XML2 format", SaveXml2);
"Save a region's data in XML2 format",
SaveXml2);
m_console.Commands.AddCommand("Archiving", false, "load xml",
"load xml [-newIDs [<x> <y> <z>]]",
"Load a region's data from XML format", LoadXml);
"Load a region's data from XML format",
LoadXml);
m_console.Commands.AddCommand("Archiving", false, "load xml2",
"load xml2",
"Load a region's data from XML2 format", LoadXml2);
"Load a region's data from XML2 format",
LoadXml2);
m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
"save prims xml2 [<prim name> <file name>]",
"Save named prim to XML2", SavePrimsXml2);
"Save named prim to XML2",
SavePrimsXml2);
m_console.Commands.AddCommand("Archiving", false, "load oar",
"load oar [--merge] [--skip-assets] [<OAR path>]",
@ -287,7 +293,8 @@ namespace OpenSim
m_console.Commands.AddCommand("Objects", false, "edit scale",
"edit scale <name> <x> <y> <z>",
"Change the scale of a named prim", HandleEditScale);
"Change the scale of a named prim",
HandleEditScale);
m_console.Commands.AddCommand("Users", false, "kick user",
"kick user <first> <last> [--force] [message]",
@ -305,31 +312,38 @@ namespace OpenSim
m_console.Commands.AddCommand("Comms", false, "show connections",
"show connections",
"Show connection data", HandleShow);
"Show connection data",
HandleShow);
m_console.Commands.AddCommand("Comms", false, "show circuits",
"show circuits",
"Show agent circuit data", HandleShow);
"Show agent circuit data",
HandleShow);
m_console.Commands.AddCommand("Comms", false, "show pending-objects",
"show pending-objects",
"Show # of objects on the pending queues of all scene viewers", HandleShow);
"Show # of objects on the pending queues of all scene viewers",
HandleShow);
m_console.Commands.AddCommand("General", false, "show modules",
"show modules",
"Show module data", HandleShow);
"Show module data",
HandleShow);
m_console.Commands.AddCommand("Regions", false, "show regions",
"show regions",
"Show region data", HandleShow);
"Show region data",
HandleShow);
m_console.Commands.AddCommand("Regions", false, "show ratings",
"show ratings",
"Show rating data", HandleShow);
"Show rating data",
HandleShow);
m_console.Commands.AddCommand("Objects", false, "backup",
"backup",
"Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
"Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
RunCommand);
m_console.Commands.AddCommand("Regions", false, "create region",
"create region [\"region name\"] <region_file.ini>",
@ -342,19 +356,23 @@ namespace OpenSim
m_console.Commands.AddCommand("Regions", false, "restart",
"restart",
"Restart all sims in this instance", RunCommand);
"Restart all sims in this instance",
RunCommand);
m_console.Commands.AddCommand("General", false, "command-script",
"command-script <script>",
"Run a command script from file", RunCommand);
"Run a command script from file",
RunCommand);
m_console.Commands.AddCommand("Regions", false, "remove-region",
"remove-region <name>",
"Remove a region from this simulator", RunCommand);
"Remove a region from this simulator",
RunCommand);
m_console.Commands.AddCommand("Regions", false, "delete-region",
"delete-region <name>",
"Delete a region from disk", RunCommand);
"Delete a region from disk",
RunCommand);
}
protected override void ShutdownSpecific()
@ -434,7 +452,7 @@ namespace OpenSim
else
presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
presence.Scene.IncomingCloseAgent(presence.UUID, force);
presence.Scene.CloseAgent(presence.UUID, force);
break;
}
}

View File

@ -96,7 +96,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
UUID spId = TestHelpers.ParseTail(0x1);
SceneHelpers.AddScenePresence(m_scene, spId);
m_scene.IncomingCloseAgent(spId, false);
m_scene.CloseAgent(spId, false);
// TODO: Add more assertions for the other aspects of event queues
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));

View File

@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.Linden
Quaternion rotation = Quaternion.Identity;
Vector3 scale = Vector3.Zero;
int state = 0;
int lastattach = 0;
if (r.Type != OSDType.Map) // not a proper req
return responsedata;
@ -224,6 +225,7 @@ namespace OpenSim.Region.ClientStack.Linden
ray_target_id = ObjMap["RayTargetId"].AsUUID();
state = ObjMap["State"].AsInteger();
lastattach = ObjMap["LastAttachPoint"].AsInteger();
try
{
ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
@ -290,6 +292,7 @@ namespace OpenSim.Region.ClientStack.Linden
//session_id = rm["session_id"].AsUUID();
state = rm["state"].AsInteger();
lastattach = rm["last_attach_point"].AsInteger();
try
{
ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
@ -331,6 +334,7 @@ namespace OpenSim.Region.ClientStack.Linden
pbs.ProfileEnd = (ushort)profile_end;
pbs.Scale = scale;
pbs.State = (byte)state;
pbs.LastAttachPoint = (byte)lastattach;
SceneObjectGroup obj = null; ;

View File

@ -277,6 +277,7 @@ namespace OpenSim.Region.ClientStack.Linden
pbs.ProfileEnd = (ushort) obj.ProfileEnd;
pbs.Scale = obj.Scale;
pbs.State = (byte) 0;
pbs.LastAttachPoint = (byte) 0;
SceneObjectPart prim = new SceneObjectPart();
prim.UUID = UUID.Random();
prim.CreatorID = AgentId;

View File

@ -304,30 +304,43 @@ namespace OpenSim.Region.ClientStack.Linden
private void RegisterCaps(UUID agentID, Caps caps)
{
if (m_fetchInventoryDescendents2Url == "")
RegisterFetchDescendentsCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
}
private void RegisterFetchDescendentsCap(UUID agentID, Caps caps, string capName, string url)
{
string capUrl;
// disable the cap clause
if (url == "")
{
return;
}
// handled by the simulator
else if (url == "localhost")
{
capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service
PollServiceInventoryEventArgs args
= new PollServiceInventoryEventArgs(m_scene, "/CAPS/" + UUID.Random() + "/", agentID);
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, capUrl, agentID);
args.Type = PollServiceEventArgs.EventType.Inventory;
caps.RegisterPollHandler("FetchInventoryDescendents2", args);
caps.RegisterPollHandler(capName, args);
}
// external handler
else
{
capUrl = url;
IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
if (handler != null)
handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl);
else
caps.RegisterHandler(capName, capUrl);
}
// MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
//
// string hostName = m_scene.RegionInfo.ExternalHostName;
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http";
//
// if (MainServer.Instance.UseSSL)
// {
// hostName = MainServer.Instance.SSLCommonName;
// port = MainServer.Instance.SSLPort;
// protocol = "https";
// }
//
// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
// m_log.DebugFormat(
// "[FETCH INVENTORY DESCENDENTS2 MODULE]: Registered capability {0} at {1} in region {2} for {3}",
// capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
}
// private void DeregisterCaps(UUID agentID, Caps caps)

View File

@ -783,7 +783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public virtual void Start()
{
m_scene.AddNewClient(this, PresenceType.User);
m_scene.AddNewAgent(this, PresenceType.User);
RefreshGroupMembership();
}
@ -12548,6 +12548,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
shape.PCode = addPacket.ObjectData.PCode;
shape.State = addPacket.ObjectData.State;
shape.LastAttachPoint = addPacket.ObjectData.State;
shape.PathBegin = addPacket.ObjectData.PathBegin;
shape.PathEnd = addPacket.ObjectData.PathEnd;
shape.PathScaleX = addPacket.ObjectData.PathScaleX;

View File

@ -1764,32 +1764,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP
endPoint = (IPEndPoint)array[0];
CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
m_log.DebugFormat(
"[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name);
// Determine which agent this packet came from
int count = 20;
bool ready = false;
while (!ready && count-- > 0)
// We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
// simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode
// and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these
// packets asynchronously, we need to account for this thread proceeding more quickly than the
// UseCircuitCode thread.
int count = 40;
while (count-- > 0)
{
if (m_scene.TryGetClient(endPoint, out client) && client.IsActive && client.SceneAgent != null)
if (m_scene.TryGetClient(endPoint, out client))
{
LLClientView llClientView = (LLClientView)client;
LLUDPClient udpClient = llClientView.UDPClient;
if (udpClient != null && udpClient.IsConnected)
ready = true;
if (!client.IsActive)
{
// This check exists to catch a condition where the client has been closed by another thread
// but has not yet been removed from the client manager (and possibly a new connection has
// not yet been established).
m_log.DebugFormat(
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
endPoint, client.Name, m_scene.Name);
}
else if (client.SceneAgent == null)
{
// This check exists to catch a condition where the new client has been added to the client
// manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too
// eager, then the new ScenePresence may not have registered a listener for this messsage
// before we try to process it.
// XXX: A better long term fix may be to add the SceneAgent before the client is added to
// the client manager
m_log.DebugFormat(
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
endPoint, client.Name, m_scene.Name);
}
else
{
m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
Thread.Sleep(200);
break;
}
}
else
{
m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
Thread.Sleep(200);
m_log.DebugFormat(
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
endPoint, m_scene.Name);
}
Thread.Sleep(200);
}
if (client == null)
{
m_log.DebugFormat(
"[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
endPoint, m_scene.Name);
return;
}
else if (!client.IsActive || client.SceneAgent == null)
{
// This check exists to catch a condition where the client has been closed by another thread
// but has not yet been removed from the client manager.
// The packet could be simply ignored but it is useful to know if this condition occurred for other debugging
// purposes.
m_log.DebugFormat(
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
endPoint, client.Name, m_scene.Name);
return;
}
IncomingPacket incomingPacket1;
@ -1810,7 +1854,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
catch (Exception e)
{
m_log.ErrorFormat(
"[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
"[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
endPoint != null ? endPoint.ToString() : "n/a",
client != null ? client.Name : "unknown",
client != null ? client.AgentId.ToString() : "unknown",
@ -1921,7 +1965,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
client.Kick("Simulator logged you out due to connection timeout.");
}
m_scene.IncomingCloseAgent(client.AgentId, true);
m_scene.CloseAgent(client.AgentId, true);
}
private void IncomingPacketHandler()
@ -2264,7 +2308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (!client.IsLoggingOut)
{
client.IsLoggingOut = true;
m_scene.IncomingCloseAgent(client.AgentId, false);
m_scene.CloseAgent(client.AgentId, false);
}
}
}

View File

@ -291,7 +291,16 @@ namespace OpenMetaverse
m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
}
}
catch (ObjectDisposedException) { }
catch (ObjectDisposedException e)
{
m_log.Error(
string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
}
catch (Exception e)
{
m_log.Error(
string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
}
}
}
@ -308,12 +317,12 @@ namespace OpenMetaverse
if (m_asyncPacketHandling)
AsyncBeginReceive();
try
{
// get the buffer that was created in AsyncBeginReceive
// this is the received data
UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
try
{
int startTick = Util.EnvironmentTickCount();
// get the length of data actually read from the socket, store it with the
@ -341,8 +350,24 @@ namespace OpenMetaverse
m_currentReceiveTimeSamples++;
}
}
catch (SocketException) { }
catch (ObjectDisposedException) { }
catch (SocketException se)
{
m_log.Error(
string.Format(
"[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
UdpReceives, se.ErrorCode),
se);
}
catch (ObjectDisposedException e)
{
m_log.Error(
string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
}
catch (Exception e)
{
m_log.Error(
string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
}
finally
{
// if (UsePools)

View File

@ -52,7 +52,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
public override void Update(int frames) {}
public override void LoadWorldMap() {}
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
{
client.OnObjectName += RecordObjectNameCall;
@ -60,9 +60,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
return null;
}
public override void RemoveClient(UUID agentID, bool someReason) {}
// public override void CloseAllAgents(uint circuitcode) {}
public override bool CloseAgent(UUID agentID, bool force) { return true; }
public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
public override void OtherRegionUp(GridRegion otherRegion) { }
public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }

View File

@ -482,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
attachPos = Vector3.Zero;
}
// AttachmentPt 0 (default) means the client chose to 'wear' the attachment.
// if the attachment point is the same as previous, make sure we get the saved
// position info.
if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
{
attachPos = group.RootPart.AttachedPos;
}
// AttachmentPt 0 means the client chose to 'wear' the attachment.
if (attachmentPt == (uint)AttachmentPoint.Default)
{
// Check object for stored attachment point
attachmentPt = group.AttachmentPoint;
}
// if we didn't find an attach point, look for where it was last attached
if (attachmentPt == 0)
{
attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
attachPos = group.RootPart.AttachedPos;
group.HasGroupChanged = true;
}
// if we still didn't find a suitable attachment point.......
if (attachmentPt == 0)
{
@ -684,6 +699,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.ClearPartAttachmentData();
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false);
so.HasGroupChanged = true;
so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
rootPart.Rezzed = DateTime.Now;
rootPart.RemFlag(PrimFlags.TemporaryOnRez);
so.AttachToBackup();

View File

@ -719,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
m_numberOfAttachEventsFired = 0;
scene.IncomingCloseAgent(presence.UUID, false);
scene.CloseAgent(presence.UUID, false);
// Check that we can't retrieve this attachment from the scene.
Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);

View File

@ -276,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (sp.IsChildAgent)
return;
sp.ControllingClient.Kick(reason);
sp.Scene.IncomingCloseAgent(sp.UUID, true);
sp.Scene.CloseAgent(sp.UUID, true);
}
private void OnIncomingInstantMessage(GridInstantMessage msg)

View File

@ -149,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
{
// m_log.DebugFormat(
// "[INVENTORY TRANSFER]: {0} IM type received from {1}",
// (InstantMessageDialog)im.dialog, client.Name);
// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
// (InstantMessageDialog)im.dialog, client.Name,
// im.fromAgentID, im.fromAgentName, im.toAgentID);
Scene scene = FindClientScene(client.AgentId);
@ -467,9 +468,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <param name="im"></param>
private void OnGridInstantMessage(GridInstantMessage im)
{
// Check if it's a type of message that we should handle
if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
|| (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
|| (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
|| (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
return;
m_log.DebugFormat(
"[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
(InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
// Check if this is ours to handle
//
Scene scene = FindClientScene(new UUID(im.toAgentID));

View File

@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
(uint)presence.AbsolutePosition.Y,
(uint)presence.AbsolutePosition.Z + 2);
m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType);
m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
GridInstantMessage m;

View File

@ -56,6 +56,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public const int DefaultMaxTransferDistance = 4095;
public const bool WaitForAgentArrivedAtDestinationDefault = true;
public string OutgoingTransferVersionName { get; set; }
/// <summary>
/// Determine the maximum entity transfer version we will use for teleports.
/// </summary>
public float MaxOutgoingTransferVersion { get; set; }
/// <summary>
/// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
/// </summary>
@ -151,9 +158,39 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <param name="source"></param>
protected virtual void InitialiseCommon(IConfigSource source)
{
string transferVersionName = "SIMULATION";
float maxTransferVersion = 0.2f;
IConfig transferConfig = source.Configs["EntityTransfer"];
if (transferConfig != null)
{
string rawVersion
= transferConfig.GetString(
"MaxOutgoingTransferVersion",
string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
string[] rawVersionComponents = rawVersion.Split(new char[] { '/' });
bool versionValid = false;
if (rawVersionComponents.Length >= 2)
versionValid = float.TryParse(rawVersionComponents[1], out maxTransferVersion);
if (!versionValid)
{
m_log.ErrorFormat(
"[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion {0} is invalid, using {1}",
rawVersion, string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
}
else
{
transferVersionName = rawVersionComponents[0];
m_log.InfoFormat(
"[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion set to {0}",
string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
}
DisableInterRegionTeleportCancellation
= transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
@ -167,6 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
MaxTransferDistance = DefaultMaxTransferDistance;
}
OutgoingTransferVersionName = transferVersionName;
MaxOutgoingTransferVersion = maxTransferVersion;
m_entityTransferStateMachine = new EntityTransferStateMachine(this);
m_Enabled = true;
@ -522,6 +562,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// </returns>
private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
{
if(MaxTransferDistance == 0)
return true;
// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
//
// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
@ -623,7 +666,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!sp.ValidateAttachments())
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
sp.Name, sp.Scene.Name, finalDestination.RegionName);
string reason;
string version;
@ -634,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
return;
}
@ -644,7 +687,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// as server attempts.
m_interRegionTeleportAttempts.Value++;
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}",
sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);
// Fixing a bug where teleporting while sitting results in the avatar ending up removed from
// both regions
@ -691,7 +736,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
}
if (version.Equals("SIMULATION/0.2"))
// We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
// use of the earlier protocol
float versionNumber = 0.1f;
string[] versionComponents = version.Split(new char[] { '/' });
if (versionComponents.Length >= 2)
float.TryParse(versionComponents[1], out versionNumber);
if (versionNumber == 0.2f && MaxOutgoingTransferVersion >= versionNumber)
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
else
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
@ -925,7 +977,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
{
if (!sp.Scene.IncomingPreCloseAgent(sp))
if (!sp.Scene.IncomingPreCloseClient(sp))
return;
// We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
@ -936,7 +988,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// an agent cannot teleport back to this region if it has teleported away.
Thread.Sleep(2000);
sp.Scene.IncomingCloseAgent(sp.UUID, false);
sp.Scene.CloseAgent(sp.UUID, false);
}
else
{
@ -1090,7 +1142,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
{
if (!sp.Scene.IncomingPreCloseAgent(sp))
if (!sp.Scene.IncomingPreCloseClient(sp))
return;
// RED ALERT!!!!
@ -1107,7 +1159,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
sp.Scene.IncomingCloseAgent(sp.UUID, false);
sp.Scene.CloseAgent(sp.UUID, false);
}
else
{

View File

@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
{
string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
uuidGatherer.GatherAssetUuids(so, ids);

View File

@ -906,6 +906,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
}
// if this was previously an attachment and is now being rezzed,
// save the old attachment info.
if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
{
group.RootPart.AttachedPos = group.AbsolutePosition;
group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
}
foreach (SceneObjectPart part in group.Parts)
{
// Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.

View File

@ -178,17 +178,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
{
//m_log.DebugFormat("[YYY]: Name request {0}", uuid);
bool foundRealName = TryGetUserNames(uuid, names);
if (names.Length == 2)
{
if (!foundRealName)
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, client.Name);
// As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
// appear to clear this when the user asks it to clear the cache, but others may not.
//
// So to avoid clients
// (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
// instead drop the request entirely.
if (TryGetUserNames(uuid, names))
client.SendNameReply(uuid, names[0], names[1]);
}
// else
// m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
// uuid, client.Name);
});
}
}
@ -391,7 +394,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
}
names[0] = "Unknown";
names[1] = "UserUMMTGUN8";
names[1] = "UserUMMTGUN9";
return false;
}
@ -599,6 +602,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
user.LastName = "@unknown";
}
}
if (parts.Length >= 2)
user.FirstName = parts[1].Replace(' ', '.');
}
@ -639,6 +643,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
protected void Init()
{
AddUser(UUID.Zero, "Unknown", "User");
RegisterConsoleCmds();
}

View File

@ -129,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
}
m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count);
m_log.DebugFormat("[HG MAP]: Resetting {0} blocks", mapBlocks.Count);
sp.ControllingClient.SendMapBlock(mapBlocks, 0);
m_SeenMapBlocks.Remove(clientID);
}

View File

@ -94,7 +94,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
m_log.InfoFormat(
"[LOCAL SIMULATION CONNECTOR]: Initialzied with connector protocol version {0}", ServiceVersion);
"[LOCAL SIMULATION CONNECTOR]: Initialized with connector protocol version {0}", ServiceVersion);
}
}
@ -235,7 +235,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// destination.RegionName, destination.RegionID);
return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData);
return m_scenes[destination.RegionID].IncomingUpdateChildAgent(cAgentData);
}
// m_log.DebugFormat(
@ -245,7 +245,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
public bool UpdateAgent(GridRegion destination, AgentPosition agentPosition)
{
if (destination == null)
return false;
@ -257,7 +257,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
foreach (Scene s in m_scenes.Values)
{
// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
s.IncomingChildAgentDataUpdate(cAgentData);
s.IncomingUpdateChildAgent(agentPosition);
}
//m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
m_scenes[destination.RegionID].IncomingCloseAgent(id, false, auth_token);
m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
return true;
}
//m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");

View File

@ -572,7 +572,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
if (!Scene.TeleportClientHome(user, s.ControllingClient))
{
s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
Scene.IncomingCloseAgent(s.UUID, false);
Scene.CloseAgent(s.UUID, false);
}
}
}
@ -807,7 +807,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
if (!Scene.TeleportClientHome(prey, s.ControllingClient))
{
s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
Scene.IncomingCloseAgent(s.UUID, false);
Scene.CloseAgent(s.UUID, false);
}
}
}
@ -830,7 +830,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
{
p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
Scene.IncomingCloseAgent(p.UUID, false);
Scene.CloseAgent(p.UUID, false);
}
}
}

View File

@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
/// Triggered when a new presence is added to the scene
/// </summary>
/// <remarks>
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
/// </remarks>
public event OnNewPresenceDelegate OnNewPresence;
@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
/// Triggered when a presence is removed from the scene
/// </summary>
/// <remarks>
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
///
/// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@ -1107,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
/// </remarks>
public event MoneyTransferEvent OnMoneyTransfer;

View File

@ -507,6 +507,9 @@ namespace OpenSim.Region.Framework.Scenes
// This MAY be problematic, if it is, another solution
// needs to be found. If inventory item flags are updated
// the viewer's notion of the item needs to be refreshed.
//
// In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
// failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
if (sendUpdate)
remoteClient.SendBulkUpdateInventory(item);
}
@ -2393,6 +2396,13 @@ namespace OpenSim.Region.Framework.Scenes
sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
}
if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
{
group.RootPart.AttachedPos = group.AbsolutePosition;
group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
}
group.FromPartID = sourcePart.UUID;
AddNewSceneObject(group, true, pos, rot, vel);

View File

@ -751,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes
m_config = config;
MinFrameTime = 0.089f;
MinMaintenanceTime = 1;
SeeIntoRegion = true;
Random random = new Random();
@ -863,6 +864,7 @@ namespace OpenSim.Region.Framework.Scenes
//Animation states
m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
@ -1338,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
Thread.Sleep(500);
// Stop all client threads.
ForEachScenePresence(delegate(ScenePresence avatar) { IncomingCloseAgent(avatar.UUID, false); });
ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
EventManager.TriggerSceneShuttingDown(this);
@ -2953,7 +2955,7 @@ namespace OpenSim.Region.Framework.Scenes
#region Add/Remove Avatar Methods
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
{
ScenePresence sp;
bool vialogin;
@ -2961,7 +2963,7 @@ namespace OpenSim.Region.Framework.Scenes
// Validation occurs in LLUDPServer
//
// XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
// XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
// each other. In practice, this does not currently occur in the code.
AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
@ -2969,9 +2971,9 @@ namespace OpenSim.Region.Framework.Scenes
// and a simultaneous one that removes it (as can happen if the client is closed at a particular point
// whilst connecting).
//
// It would be easier to lock across all NewUserConnection(), AddNewClient() and
// It would be easier to lock across all NewUserConnection(), AddNewAgent() and
// RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
// response in some module listening to AddNewClient()) from holding up unrelated agent calls.
// response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
//
// In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
// AddNewClient() operations (though not other ops).
@ -2988,7 +2990,7 @@ namespace OpenSim.Region.Framework.Scenes
// XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
// could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
// other problems, and possible the code calling AddNewClient() should ensure that no client is already
// other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
// connected.
if (sp == null)
{
@ -3021,6 +3023,9 @@ namespace OpenSim.Region.Framework.Scenes
// We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
// client is for a root or child agent.
// XXX: This may be better set for a new client before that client is added to the client manager.
// But need to know what happens in the case where a ScenePresence is already present (and if this
// actually occurs).
client.SceneAgent = sp;
// This is currently also being done earlier in NewUserConnection for real users to see if this
@ -3130,7 +3135,7 @@ namespace OpenSim.Region.Framework.Scenes
{
PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
IncomingCloseAgent(sp.UUID, false);
CloseAgent(sp.UUID, false);
}
// BANG! SLASH!
@ -3554,7 +3559,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name='closeChildAgents'>
/// Close the neighbour child agents associated with this client.
/// </param>
public override void RemoveClient(UUID agentID, bool closeChildAgents)
public void RemoveClient(UUID agentID, bool closeChildAgents)
{
AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
@ -3940,7 +3945,7 @@ namespace OpenSim.Region.Framework.Scenes
sp.Name, sp.UUID, RegionInfo.RegionName);
if (sp.ControllingClient != null)
IncomingCloseAgent(sp.UUID, true);
CloseAgent(sp.UUID, true);
sp = null;
}
@ -4025,19 +4030,6 @@ namespace OpenSim.Region.Framework.Scenes
// uses down the line.
sp.TeleportFlags = (TPFlags)teleportFlags;
// We must carry out a further authorization check if there's an
// attempt to make a child agent into a root agent, since SeeIntoRegion may have allowed a child
// agent to login to a region where a full avatar would not be allowed.
//
// We determine whether this is a CreateAgent for a future non-child agent by inspecting
// TeleportFlags, which will be default for a child connection. This relies on input from the source
// region.
if (sp.TeleportFlags != TPFlags.Default)
{
if (!AuthorizeUser(acd, false, out reason))
return false;
}
if (sp.IsChildAgent)
{
m_log.DebugFormat(
@ -4469,7 +4461,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
/// Appearance, animations, position, etc.</param>
/// <returns>true if we handled it.</returns>
public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData)
public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
{
m_log.DebugFormat(
"[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
@ -4487,7 +4479,7 @@ namespace OpenSim.Region.Framework.Scenes
ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
if (nearestParcel == null)
{
m_log.DebugFormat(
m_log.InfoFormat(
"[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
cAgentData.AgentID, RegionInfo.RegionName);
@ -4497,7 +4489,7 @@ namespace OpenSim.Region.Framework.Scenes
// We have to wait until the viewer contacts this region
// after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
// or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
// a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
if (sp != null)
@ -4512,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
}
sp.ChildAgentDataUpdate(cAgentData);
sp.UpdateChildAgent(cAgentData);
int ntimes = 20;
if (cAgentData.SenderWantsToWaitForRoot)
@ -4520,9 +4512,14 @@ namespace OpenSim.Region.Framework.Scenes
while (sp.IsChildAgent && ntimes-- > 0)
Thread.Sleep(1000);
m_log.DebugFormat(
"[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes);
if (sp.IsChildAgent)
m_log.WarnFormat(
"[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
sp.Name, sp.UUID, Name);
else
m_log.InfoFormat(
"[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
sp.Name, sp.UUID, Name, 20 - ntimes);
if (sp.IsChildAgent)
return false;
@ -4540,7 +4537,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
/// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
/// <returns>true if we handled it.</returns>
public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData)
public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
{
//m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
@ -4560,7 +4557,7 @@ namespace OpenSim.Region.Framework.Scenes
uint tRegionX = RegionInfo.RegionLocX;
uint tRegionY = RegionInfo.RegionLocY;
//Send Data to ScenePresence
childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
// Not Implemented:
//TODO: Do we need to pass the message on to one of our neighbors?
}
@ -4610,7 +4607,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="force"></param>
/// <param name="auth_token"></param>
/// <returns></returns>
public bool IncomingCloseAgent(UUID agentID, bool force, string auth_token)
public bool CloseAgent(UUID agentID, bool force, string auth_token)
{
//m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
@ -4628,7 +4625,7 @@ namespace OpenSim.Region.Framework.Scenes
if (acd.SessionID.ToString() == auth_token)
{
return IncomingCloseAgent(agentID, force);
return CloseAgent(agentID, force);
}
else
{
@ -4640,27 +4637,27 @@ namespace OpenSim.Region.Framework.Scenes
return false;
}
public bool IncomingCloseAgent(UUID agentID)
{
return IncomingCloseAgent(agentID, false);
}
// public bool IncomingCloseAgent(UUID agentID)
// {
// return IncomingCloseAgent(agentID, false);
// }
public bool IncomingCloseChildAgent(UUID agentID)
{
return IncomingCloseAgent(agentID, true);
}
// public bool IncomingCloseChildAgent(UUID agentID)
// {
// return IncomingCloseAgent(agentID, true);
// }
/// <summary>
/// Tell a single agent to prepare to close.
/// Tell a single client to prepare to close.
/// </summary>
/// <remarks>
/// This should only be called if we may close the agent but there will be some delay in so doing. Meant for
/// internal use - other callers should almost certainly called IncomingCloseAgent().
/// This should only be called if we may close the client but there will be some delay in so doing. Meant for
/// internal use - other callers should almost certainly called CloseClient().
/// </remarks>
/// <param name="sp"></param>
/// <returns>true if pre-close state notification was successful. false if the agent
/// was not in a state where it could transition to pre-close.</returns>
public bool IncomingPreCloseAgent(ScenePresence sp)
public bool IncomingPreCloseClient(ScenePresence sp)
{
lock (m_removeClientLock)
{
@ -4702,7 +4699,7 @@ namespace OpenSim.Region.Framework.Scenes
/// Force the agent to close even if it might be in the middle of some other operation. You do not want to
/// force unless you are absolutely sure that the agent is dead and a normal close is not working.
/// </param>
public bool IncomingCloseAgent(UUID agentID, bool force)
public override bool CloseAgent(UUID agentID, bool force)
{
ScenePresence sp;
@ -4713,7 +4710,7 @@ namespace OpenSim.Region.Framework.Scenes
if (sp == null)
{
m_log.DebugFormat(
"[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
"[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
agentID, Name);
return false;
@ -4722,7 +4719,7 @@ namespace OpenSim.Region.Framework.Scenes
if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
{
m_log.DebugFormat(
"[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
"[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
sp.Name, Name, sp.LifecycleState);
return false;

View File

@ -217,21 +217,9 @@ namespace OpenSim.Region.Framework.Scenes
#region Add/Remove Agent/Avatar
public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
/// <summary>
/// Remove the given client from the scene.
/// </summary>
/// <remarks>
/// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
/// to properly operate the state machine and avoid race conditions with other close requests (such as directly
/// from viewers).
/// </remarks>
/// <param name='agentID'>ID of agent to close</param>
/// <param name='closeChildAgents'>
/// Close the neighbour child agents associated with this client.
/// </param>
public abstract void RemoveClient(UUID agentID, bool closeChildAgents);
public abstract bool CloseAgent(UUID agentID, bool force);
public bool TryGetScenePresence(UUID agentID, out object scenePresence)
{

View File

@ -2960,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes
//ParentGroup.RootPart.m_groupPosition = newpos;
}
if (pa != null && ParentID != 0 && ParentGroup != null)
{
// Special case where a child object is requesting property updates.
// This happens when linksets are modified to use flexible links rather than
// the default links.
// The simulator code presumes that child parts are only modified by scripts
// so the logic for changing position/rotation/etc does not take into
// account the physical object actually moving.
// This code updates the offset position and rotation of the child and then
// lets the update code push the update to the viewer.
// Since physics engines do not normally generate this event for linkset children,
// this code will not be active unless you have a specially configured
// physics engine.
Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
m_offsetPosition = pa.Position - m_groupPosition;
RotationOffset = pa.Orientation * invRootRotation;
// m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
// "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
}
ScheduleTerseUpdate();
}

View File

@ -320,7 +320,21 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
private string m_callbackURI;
public UUID m_originRegionID;
/// <summary>
/// Records the region from which this presence originated, if not from login.
/// </summary>
/// <remarks>
/// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
/// CompleteMovement and made the previous child agent a root agent.
/// </remarks>
private UUID m_originRegionID;
/// <summary>
/// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
/// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
/// it is a value type.
/// </summary>
private object m_originRegionIDAccessLock = new object();
/// <summary>
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
@ -975,11 +989,11 @@ namespace OpenSim.Region.Framework.Scenes
/// This method is on the critical path for transferring an avatar from one region to another. Delay here
/// delays that crossing.
/// </summary>
public void MakeRootAgent(Vector3 pos, bool isFlying)
private void MakeRootAgent(Vector3 pos, bool isFlying)
{
m_log.InfoFormat(
"[SCENE]: Upgrading child to root agent for {0} in {1}",
Name, m_scene.RegionInfo.RegionName);
// m_log.InfoFormat(
// "[SCENE]: Upgrading child to root agent for {0} in {1}",
// Name, m_scene.RegionInfo.RegionName);
if (ParentUUID != UUID.Zero)
{
@ -1545,15 +1559,26 @@ namespace OpenSim.Region.Framework.Scenes
private bool WaitForUpdateAgent(IClientAPI client)
{
// Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero
// Before the source region executes UpdateAgent
// (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
// m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
// viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
int count = 50;
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
UUID originID;
lock (m_originRegionIDAccessLock)
originID = m_originRegionID;
while (originID.Equals(UUID.Zero) && count-- > 0)
{
lock (m_originRegionIDAccessLock)
originID = m_originRegionID;
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
Thread.Sleep(200);
}
if (m_originRegionID.Equals(UUID.Zero))
if (originID.Equals(UUID.Zero))
{
// Movement into region will fail
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
@ -1576,9 +1601,9 @@ namespace OpenSim.Region.Framework.Scenes
{
// DateTime startTime = DateTime.Now;
m_log.DebugFormat(
m_log.InfoFormat(
"[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
client.Name, Scene.RegionInfo.RegionName, AbsolutePosition);
client.Name, Scene.Name, AbsolutePosition);
// Make sure it's not a login agent. We don't want to wait for updates during login
if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
@ -1633,7 +1658,12 @@ namespace OpenSim.Region.Framework.Scenes
"[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
client.Name, client.AgentId, m_callbackURI);
Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
UUID originID;
lock (m_originRegionIDAccessLock)
originID = m_originRegionID;
Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
m_callbackURI = null;
}
// else
@ -3089,7 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
// If we are using the the cached appearance then send it out to everyone
if (cachedappearance)
{
m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name);
m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
// If the avatars baked textures are all in the cache, then we have a
// complete appearance... send it out, if not, then we'll send it when
@ -3553,7 +3583,7 @@ namespace OpenSim.Region.Framework.Scenes
#region Child Agent Updates
public void ChildAgentDataUpdate(AgentData cAgentData)
public void UpdateChildAgent(AgentData cAgentData)
{
// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
if (!IsChildAgent)
@ -3563,15 +3593,17 @@ namespace OpenSim.Region.Framework.Scenes
}
private static Vector3 marker = new Vector3(-1f, -1f, -1f);
private void RaiseUpdateThrottles()
{
m_scene.EventManager.TriggerThrottleUpdate(this);
}
/// <summary>
/// This updates important decision making data about a child agent
/// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
/// </summary>
public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
{
if (!IsChildAgent)
return;
@ -3679,6 +3711,7 @@ namespace OpenSim.Region.Framework.Scenes
private void CopyFrom(AgentData cAgent)
{
lock (m_originRegionIDAccessLock)
m_originRegionID = cAgent.RegionID;
m_callbackURI = cAgent.CallbackURI;

View File

@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos);
m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
m_ShapeXmlProcessors.Add("State", ProcessShpState);
m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
}
private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
{
obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
}
private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
{
obj.DynAttrs.ReadXml(reader);
@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
}
private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
{
shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
}
private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
{
shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@ -1345,6 +1357,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
if (sop.MediaUrl != null)
writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
WriteVector(writer, "AttachedPos", sop.AttachedPos);
if (sop.DynAttrs.CountNamespaces > 0)
{
@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
writer.WriteElementString("State", shp.State.ToString());
writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);

View File

@ -146,7 +146,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
}
[Test]
public void TestCloseAgent()
public void TestCloseClient()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
@ -154,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene();
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
scene.IncomingCloseAgent(sp.UUID, false);
scene.CloseAgent(sp.UUID, false);
Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// *** This is the second stage, where the client established a child agent/scene presence using the
// circuit code given to the scene in stage 1 ***
TestClient client = new TestClient(acd, scene);
scene.AddNewClient(client, PresenceType.User);
scene.AddNewAgent(client, PresenceType.User);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@ -279,7 +279,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// string reason;
// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
// testclient = new TestClient(agent, scene);
// scene.AddNewClient(testclient);
// scene.AddNewAgent(testclient);
//
// ScenePresence presence = scene.GetScenePresence(agent1);
//

View File

@ -79,7 +79,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// TODO: Need to add tests for other ICapabiltiesModule methods.
scene.IncomingCloseAgent(sp.UUID, false);
// scene.IncomingCloseAgent(sp.UUID, false);
// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
scene.CloseAgent(sp.UUID, false);
// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
// TODO: Need to add tests for other ICapabiltiesModule methods.

View File

@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.CoreModules.Framework;
using OpenSim.Region.CoreModules.Framework.EntityTransfer;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
using OpenSim.Region.CoreModules.World.Permissions;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
@ -159,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
}
/// <summary>
/// Test a cross attempt where the user can see into the neighbour but does not have permission to become
/// root there.
/// </summary>
[Test]
public void TestCrossOnSameSimulatorNoRootDestPerm()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID userId = TestHelpers.ParseTail(0x1);
EntityTransferModule etmA = new EntityTransferModule();
EntityTransferModule etmB = new EntityTransferModule();
LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
IConfigSource config = new IniConfigSource();
IConfig modulesConfig = config.AddConfig("Modules");
modulesConfig.Set("EntityTransferModule", etmA.Name);
modulesConfig.Set("SimulationServices", lscm.Name);
SceneHelpers sh = new SceneHelpers();
TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
// We need to set up the permisions module on scene B so that our later use of agent limit to deny
// QueryAccess won't succeed anyway because administrators are always allowed in and the default
// IsAdministrator if no permissions module is present is true.
// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
TestClient tc = new TestClient(acd, sceneA);
List<TestClient> destinationTestClients = new List<TestClient>();
EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
// Make sure sceneB will not accept this avatar.
sceneB.RegionInfo.EstateSettings.PublicAccess = false;
ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
originalSp.AbsolutePosition = new Vector3(128, 32, 10);
AgentUpdateArgs moveArgs = new AgentUpdateArgs();
//moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
moveArgs.SessionID = acd.SessionID;
originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
sceneA.Update(1);
// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
// FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
// But really we want to do this in a more robust way.
for (int i = 0; i < 100; i++)
{
sceneA.Update(1);
// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
}
// sceneA agent should still be root
ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
// sceneB agent should also still be root
Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
// sceneB should ignore unauthorized attempt to upgrade agent to root
TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
int agentMovementCompleteReceived = 0;
sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
sceneBTc.CompleteMovement();
Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
}
}
}

View File

@ -169,6 +169,19 @@ namespace OpenSim.Region.Framework.Scenes
if (part.Shape.SculptTexture != UUID.Zero)
assetUuids[part.Shape.SculptTexture] = AssetType.Texture;
if (part.Shape.ProjectionTextureUUID != UUID.Zero)
assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture;
if (part.CollisionSound != UUID.Zero)
assetUuids[part.CollisionSound] = AssetType.Sound;
if (part.ParticleSystem.Length > 0)
{
Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
if (ps.Texture != UUID.Zero)
assetUuids[ps.Texture] = AssetType.Texture;
}
TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
// Now analyze this prim's inventory items to preserve all the uuids that they reference

View File

@ -908,7 +908,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public void Start()
{
m_scene.AddNewClient(this, PresenceType.User);
m_scene.AddNewAgent(this, PresenceType.User);
// Mimicking LLClientView which gets always set appearance from client.
AvatarAppearance appearance;

View File

@ -29,12 +29,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using OpenSim.Framework;
using OpenSim.Region.CoreModules;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
using Mono.Addins;
using Nini.Config;
@ -60,6 +62,10 @@ public class ExtendedPhysics : INonSharedRegionModule
// Per prim functions. See BSPrim.
public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
public const string PhysFunctChangeLinkFixed = "BulletSim.ChangeLinkFixed";
public const string PhysFunctChangeLinkType = "BulletSim.ChangeLinkType";
public const string PhysFunctGetLinkType = "BulletSim.GetLinkType";
public const string PhysFunctChangeLinkParams = "BulletSim.ChangeLinkParams";
// =============================================================
@ -155,7 +161,7 @@ public class ExtendedPhysics : INonSharedRegionModule
}
[ScriptConstant]
public static int PHYS_CENTER_OF_MASS = 1 << 0;
public const int PHYS_CENTER_OF_MASS = 1 << 0;
[ScriptInvocation]
public string physGetEngineType(UUID hostID, UUID scriptID)
@ -171,11 +177,11 @@ public class ExtendedPhysics : INonSharedRegionModule
}
[ScriptConstant]
public static int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
[ScriptConstant]
public static int PHYS_LINKSET_TYPE_COMPOUND = 1;
public const int PHYS_LINKSET_TYPE_COMPOUND = 1;
[ScriptConstant]
public static int PHYS_LINKSET_TYPE_MANUAL = 2;
public const int PHYS_LINKSET_TYPE_MANUAL = 2;
[ScriptInvocation]
public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
@ -195,10 +201,38 @@ public class ExtendedPhysics : INonSharedRegionModule
if (rootPart != null)
{
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
PhysicsActor rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
if (rootPhysActor.IsPhysical)
{
// Change a physical linkset by making non-physical, waiting for one heartbeat so all
// the prim and linkset state is updated, changing the type and making the
// linkset physical again.
containingGroup.ScriptSetPhysicsStatus(false);
Thread.Sleep(150); // longer than one heartbeat tick
// A kludge for the moment.
// Since compound linksets move the children but don't generate position updates to the
// simulator, it is possible for compound linkset children to have out-of-sync simulator
// and physical positions. The following causes the simulator to push the real child positions
// down into the physics engine to get everything synced.
containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition);
containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation);
object[] parms2 = { rootPhysActor, null, linksetType };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
Thread.Sleep(150); // longer than one heartbeat tick
containingGroup.ScriptSetPhysicsStatus(true);
}
else
{
// Non-physical linksets don't have a physical instantiation so there is no state to
// worry about being updated.
object[] parms2 = { rootPhysActor, null, linksetType };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
}
}
else
{
@ -223,7 +257,6 @@ public class ExtendedPhysics : INonSharedRegionModule
public int physGetLinksetType(UUID hostID, UUID scriptID)
{
int ret = -1;
if (!Enabled) return ret;
// The part that is requesting the change.
@ -237,10 +270,11 @@ public class ExtendedPhysics : INonSharedRegionModule
if (rootPart != null)
{
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
PhysicsActor rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
ret = (int)rootPhysActor.Extension(PhysFunctGetLinksetType);
object[] parms2 = { rootPhysActor, null };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
}
else
{
@ -260,5 +294,288 @@ public class ExtendedPhysics : INonSharedRegionModule
}
return ret;
}
[ScriptConstant]
public const int PHYS_LINK_TYPE_FIXED = 1234;
[ScriptConstant]
public const int PHYS_LINK_TYPE_HINGE = 4;
[ScriptConstant]
public const int PHYS_LINK_TYPE_SPRING = 9;
[ScriptConstant]
public const int PHYS_LINK_TYPE_6DOF = 6;
[ScriptConstant]
public const int PHYS_LINK_TYPE_SLIDER = 7;
// physChangeLinkType(integer linkNum, integer typeCode)
[ScriptInvocation]
public int physChangeLinkType(UUID hostID, UUID scriptID, int linkNum, int typeCode)
{
int ret = -1;
if (!Enabled) return ret;
PhysicsActor rootPhysActor;
PhysicsActor childPhysActor;
if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
{
object[] parms2 = { rootPhysActor, childPhysActor, typeCode };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
}
return ret;
}
// physGetLinkType(integer linkNum)
[ScriptInvocation]
public int physGetLinkType(UUID hostID, UUID scriptID, int linkNum)
{
int ret = -1;
if (!Enabled) return ret;
PhysicsActor rootPhysActor;
PhysicsActor childPhysActor;
if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
{
object[] parms2 = { rootPhysActor, childPhysActor };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinkType, parms2));
}
return ret;
}
// physChangeLinkFixed(integer linkNum)
// Change the link between the root and the linkNum into a fixed, static physical connection.
[ScriptInvocation]
public int physChangeLinkFixed(UUID hostID, UUID scriptID, int linkNum)
{
int ret = -1;
if (!Enabled) return ret;
PhysicsActor rootPhysActor;
PhysicsActor childPhysActor;
if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
{
object[] parms2 = { rootPhysActor, childPhysActor , PHYS_LINK_TYPE_FIXED };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
}
return ret;
}
// Code for specifying params.
// The choice if 14400 is arbitrary and only serves to catch parameter code misuse.
public const int PHYS_PARAM_MIN = 14401;
[ScriptConstant]
public const int PHYS_PARAM_FRAMEINA_LOC = 14401;
[ScriptConstant]
public const int PHYS_PARAM_FRAMEINA_ROT = 14402;
[ScriptConstant]
public const int PHYS_PARAM_FRAMEINB_LOC = 14403;
[ScriptConstant]
public const int PHYS_PARAM_FRAMEINB_ROT = 14404;
[ScriptConstant]
public const int PHYS_PARAM_LINEAR_LIMIT_LOW = 14405;
[ScriptConstant]
public const int PHYS_PARAM_LINEAR_LIMIT_HIGH = 14406;
[ScriptConstant]
public const int PHYS_PARAM_ANGULAR_LIMIT_LOW = 14407;
[ScriptConstant]
public const int PHYS_PARAM_ANGULAR_LIMIT_HIGH = 14408;
[ScriptConstant]
public const int PHYS_PARAM_USE_FRAME_OFFSET = 14409;
[ScriptConstant]
public const int PHYS_PARAM_ENABLE_TRANSMOTOR = 14410;
[ScriptConstant]
public const int PHYS_PARAM_TRANSMOTOR_MAXVEL = 14411;
[ScriptConstant]
public const int PHYS_PARAM_TRANSMOTOR_MAXFORCE = 14412;
[ScriptConstant]
public const int PHYS_PARAM_CFM = 14413;
[ScriptConstant]
public const int PHYS_PARAM_ERP = 14414;
[ScriptConstant]
public const int PHYS_PARAM_SOLVER_ITERATIONS = 14415;
[ScriptConstant]
public const int PHYS_PARAM_SPRING_AXIS_ENABLE = 14416;
[ScriptConstant]
public const int PHYS_PARAM_SPRING_DAMPING = 14417;
[ScriptConstant]
public const int PHYS_PARAM_SPRING_STIFFNESS = 14418;
[ScriptConstant]
public const int PHYS_PARAM_LINK_TYPE = 14419;
[ScriptConstant]
public const int PHYS_PARAM_USE_LINEAR_FRAMEA = 14420;
[ScriptConstant]
public const int PHYS_PARAM_SPRING_EQUILIBRIUM_POINT = 14421;
public const int PHYS_PARAM_MAX = 14421;
// Used when specifying a parameter that has settings for the three linear and three angular axis
[ScriptConstant]
public const int PHYS_AXIS_ALL = -1;
[ScriptConstant]
public const int PHYS_AXIS_LINEAR_ALL = -2;
[ScriptConstant]
public const int PHYS_AXIS_ANGULAR_ALL = -3;
[ScriptConstant]
public const int PHYS_AXIS_LINEAR_X = 0;
[ScriptConstant]
public const int PHYS_AXIS_LINEAR_Y = 1;
[ScriptConstant]
public const int PHYS_AXIS_LINEAR_Z = 2;
[ScriptConstant]
public const int PHYS_AXIS_ANGULAR_X = 3;
[ScriptConstant]
public const int PHYS_AXIS_ANGULAR_Y = 4;
[ScriptConstant]
public const int PHYS_AXIS_ANGULAR_Z = 5;
// physChangeLinkParams(integer linkNum, [ PHYS_PARAM_*, value, PHYS_PARAM_*, value, ...])
[ScriptInvocation]
public int physChangeLinkParams(UUID hostID, UUID scriptID, int linkNum, object[] parms)
{
int ret = -1;
if (!Enabled) return ret;
PhysicsActor rootPhysActor;
PhysicsActor childPhysActor;
if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
{
object[] parms2 = AddToBeginningOfArray(rootPhysActor, childPhysActor, parms);
ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkParams, parms2));
}
return ret;
}
private bool GetRootPhysActor(UUID hostID, out PhysicsActor rootPhysActor)
{
SceneObjectGroup containingGroup;
SceneObjectPart rootPart;
return GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor);
}
private bool GetRootPhysActor(UUID hostID, out SceneObjectGroup containingGroup, out SceneObjectPart rootPart, out PhysicsActor rootPhysActor)
{
bool ret = false;
rootPhysActor = null;
containingGroup = null;
rootPart = null;
SceneObjectPart requestingPart;
requestingPart = BaseScene.GetSceneObjectPart(hostID);
if (requestingPart != null)
{
// The type is is always on the root of a linkset.
containingGroup = requestingPart.ParentGroup;
if (containingGroup != null && !containingGroup.IsDeleted)
{
rootPart = containingGroup.RootPart;
if (rootPart != null)
{
rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
ret = true;
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
LogHeader, rootPart.Name, hostID);
}
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not exist. RequestingPartName={1}, hostID={2}",
LogHeader, requestingPart.Name, hostID);
}
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Containing group missing or deleted. hostID={1}", LogHeader, hostID);
}
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: cannot find script object in scene. hostID={1}", LogHeader, hostID);
}
return ret;
}
// Find the root and child PhysActors based on the linkNum.
// Return 'true' if both are found and returned.
private bool GetRootAndChildPhysActors(UUID hostID, int linkNum, out PhysicsActor rootPhysActor, out PhysicsActor childPhysActor)
{
bool ret = false;
rootPhysActor = null;
childPhysActor = null;
SceneObjectGroup containingGroup;
SceneObjectPart rootPart;
if (GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor))
{
SceneObjectPart linkPart = containingGroup.GetLinkNumPart(linkNum);
if (linkPart != null)
{
childPhysActor = linkPart.PhysActor;
if (childPhysActor != null)
{
ret = true;
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Link part has no physical actor. rootName={1}, hostID={2}, linknum={3}",
LogHeader, rootPart.Name, hostID, linkNum);
}
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Could not find linknum part. rootName={1}, hostID={2}, linknum={3}",
LogHeader, rootPart.Name, hostID, linkNum);
}
}
else
{
m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
LogHeader, rootPart.Name, hostID);
}
return ret;
}
// Return an array of objects with the passed object as the first object of a new array
private object[] AddToBeginningOfArray(object firstOne, object secondOne, object[] prevArray)
{
object[] newArray = new object[2 + prevArray.Length];
newArray[0] = firstOne;
newArray[1] = secondOne;
prevArray.CopyTo(newArray, 2);
return newArray;
}
// Extension() returns an object. Convert that object into the integer error we expect to return.
private int MakeIntError(object extensionRet)
{
int ret = -1;
if (extensionRet != null)
{
try
{
ret = (int)extensionRet;
}
catch
{
ret = -1;
}
}
return ret;
}
}
}

View File

@ -176,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
lock (m_avatars)
{
scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
scene.AddNewClient(npcAvatar, PresenceType.Npc);
scene.AddNewAgent(npcAvatar, PresenceType.Npc);
ScenePresence sp;
if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@ -208,7 +208,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
// m_log.DebugFormat(
// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
// sp.Name, pos, scene.RegionInfo.RegionName,
// noFly, landAtTarget);
sp.MoveToTarget(pos, noFly, landAtTarget);
sp.SetAlwaysRun = running;
@ -285,9 +286,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
ScenePresence sp;
if (scene.TryGetScenePresence(agentID, out sp))
{
sp.HandleAgentRequestSit(m_avatars[agentID], agentID,
partID, Vector3.Zero);
//sp.HandleAgentSit(m_avatars[agentID], agentID);
sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
return true;
}
@ -378,11 +377,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
agentID, av.Name);
*/
scene.IncomingCloseAgent(agentID, false);
// scene.RemoveClient(agentID, false);
scene.CloseAgent(agentID, false);
m_avatars.Remove(agentID);
// m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name);
/*
m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
agentID, av.Name);
*/
return true;
}
}

View File

@ -596,6 +596,60 @@ public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, flo
return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
}
public override bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.HingeSetLimits2(constrainu.ptr, low, high, softness, bias, relaxation);
}
public override bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.ConstraintSpringEnable2(constrainu.ptr, index, numericTrueFalse);
}
public override bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.ConstraintSpringSetEquilibriumPoint2(constrainu.ptr, index, equilibriumPoint);
}
public override bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.ConstraintSpringSetStiffness2(constrainu.ptr, index, stiffnesss);
}
public override bool SpringSetDamping(BulletConstraint constrain, int index, float damping)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.ConstraintSpringSetDamping2(constrainu.ptr, index, damping);
}
public override bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.SliderSetLimits2(constrainu.ptr, lowerUpper, linAng, val);
}
public override bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.SliderSet2(constrainu.ptr, softRestDamp, dirLimOrtho, linAng, val);
}
public override bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.SliderMotorEnable2(constrainu.ptr, linAng, numericTrueFalse);
}
public override bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
return BSAPICPP.SliderMotor2(constrainu.ptr, forceVel, linAng, val);
}
public override bool CalculateTransforms(BulletConstraint constrain)
{
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
@ -671,6 +725,13 @@ public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
}
public override bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj)
{
BulletWorldUnman worldu = world as BulletWorldUnman;
BulletBodyUnman bodyu = obj as BulletBodyUnman;
return BSAPICPP.ClearCollisionProxyCache2(worldu.ptr, bodyu.ptr);
}
public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
{
BulletWorldUnman worldu = world as BulletWorldUnman;
@ -1600,6 +1661,33 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool HingeSetLimits2(IntPtr constrain, float low, float high, float softness, float bias, float relaxation);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ConstraintSpringEnable2(IntPtr constrain, int index, float numericTrueFalse);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ConstraintSpringSetEquilibriumPoint2(IntPtr constrain, int index, float equilibriumPoint);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ConstraintSpringSetStiffness2(IntPtr constrain, int index, float stiffness);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ConstraintSpringSetDamping2(IntPtr constrain, int index, float damping);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SliderSetLimits2(IntPtr constrain, int lowerUpper, int linAng, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SliderSet2(IntPtr constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SliderMotorEnable2(IntPtr constrain, int linAng, float numericTrueFalse);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SliderMotor2(IntPtr constrain, int forceVel, int linAng, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CalculateTransforms2(IntPtr constrain);
@ -1631,6 +1719,9 @@ public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ClearCollisionProxyCache2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);

View File

@ -169,6 +169,19 @@ private sealed class BulletConstraintXNA : BulletConstraint
return true;
}
public override bool ClearCollisionProxyCache(BulletWorld pWorld, BulletBody pBody)
{
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
CollisionObject collisionObject = ((BulletBodyXNA)pBody).body;
if (body != null && collisionObject != null && collisionObject.GetBroadphaseHandle() != null)
{
world.RemoveCollisionObject(collisionObject);
world.AddCollisionObject(collisionObject);
}
return true;
}
public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects)
{
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
@ -752,6 +765,214 @@ private sealed class BulletConstraintXNA : BulletConstraint
constraint.SetBreakingImpulseThreshold(threshold);
return true;
}
public override bool HingeSetLimits(BulletConstraint pConstraint, float low, float high, float softness, float bias, float relaxation)
{
HingeConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as HingeConstraint;
if (softness == HINGE_NOT_SPECIFIED)
constraint.SetLimit(low, high);
else
constraint.SetLimit(low, high, softness, bias, relaxation);
return true;
}
public override bool SpringEnable(BulletConstraint pConstraint, int index, float numericTrueFalse)
{
Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
constraint.EnableSpring(index, (numericTrueFalse == 0f ? false : true));
return true;
}
public override bool SpringSetEquilibriumPoint(BulletConstraint pConstraint, int index, float equilibriumPoint)
{
Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
if (index == SPRING_NOT_SPECIFIED)
{
constraint.SetEquilibriumPoint();
}
else
{
if (equilibriumPoint == SPRING_NOT_SPECIFIED)
constraint.SetEquilibriumPoint(index);
else
constraint.SetEquilibriumPoint(index, equilibriumPoint);
}
return true;
}
public override bool SpringSetStiffness(BulletConstraint pConstraint, int index, float stiffness)
{
Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
constraint.SetStiffness(index, stiffness);
return true;
}
public override bool SpringSetDamping(BulletConstraint pConstraint, int index, float damping)
{
Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
constraint.SetDamping(index, damping);
return true;
}
public override bool SliderSetLimits(BulletConstraint pConstraint, int lowerUpper, int linAng, float val)
{
SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
switch (lowerUpper)
{
case SLIDER_LOWER_LIMIT:
switch (linAng)
{
case SLIDER_LINEAR:
constraint.SetLowerLinLimit(val);
break;
case SLIDER_ANGULAR:
constraint.SetLowerAngLimit(val);
break;
}
break;
case SLIDER_UPPER_LIMIT:
switch (linAng)
{
case SLIDER_LINEAR:
constraint.SetUpperLinLimit(val);
break;
case SLIDER_ANGULAR:
constraint.SetUpperAngLimit(val);
break;
}
break;
}
return true;
}
public override bool SliderSet(BulletConstraint pConstraint, int softRestDamp, int dirLimOrtho, int linAng, float val)
{
SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
switch (softRestDamp)
{
case SLIDER_SET_SOFTNESS:
switch (dirLimOrtho)
{
case SLIDER_SET_DIRECTION:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetSoftnessDirLin(val); break;
case SLIDER_ANGULAR: constraint.SetSoftnessDirAng(val); break;
}
break;
case SLIDER_SET_LIMIT:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetSoftnessLimLin(val); break;
case SLIDER_ANGULAR: constraint.SetSoftnessLimAng(val); break;
}
break;
case SLIDER_SET_ORTHO:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetSoftnessOrthoLin(val); break;
case SLIDER_ANGULAR: constraint.SetSoftnessOrthoAng(val); break;
}
break;
}
break;
case SLIDER_SET_RESTITUTION:
switch (dirLimOrtho)
{
case SLIDER_SET_DIRECTION:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetRestitutionDirLin(val); break;
case SLIDER_ANGULAR: constraint.SetRestitutionDirAng(val); break;
}
break;
case SLIDER_SET_LIMIT:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetRestitutionLimLin(val); break;
case SLIDER_ANGULAR: constraint.SetRestitutionLimAng(val); break;
}
break;
case SLIDER_SET_ORTHO:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetRestitutionOrthoLin(val); break;
case SLIDER_ANGULAR: constraint.SetRestitutionOrthoAng(val); break;
}
break;
}
break;
case SLIDER_SET_DAMPING:
switch (dirLimOrtho)
{
case SLIDER_SET_DIRECTION:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetDampingDirLin(val); break;
case SLIDER_ANGULAR: constraint.SetDampingDirAng(val); break;
}
break;
case SLIDER_SET_LIMIT:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetDampingLimLin(val); break;
case SLIDER_ANGULAR: constraint.SetDampingLimAng(val); break;
}
break;
case SLIDER_SET_ORTHO:
switch (linAng)
{
case SLIDER_LINEAR: constraint.SetDampingOrthoLin(val); break;
case SLIDER_ANGULAR: constraint.SetDampingOrthoAng(val); break;
}
break;
}
break;
}
return true;
}
public override bool SliderMotorEnable(BulletConstraint pConstraint, int linAng, float numericTrueFalse)
{
SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
switch (linAng)
{
case SLIDER_LINEAR:
constraint.SetPoweredLinMotor(numericTrueFalse == 0.0 ? false : true);
break;
case SLIDER_ANGULAR:
constraint.SetPoweredAngMotor(numericTrueFalse == 0.0 ? false : true);
break;
}
return true;
}
public override bool SliderMotor(BulletConstraint pConstraint, int forceVel, int linAng, float val)
{
SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
switch (forceVel)
{
case SLIDER_MOTOR_VELOCITY:
switch (linAng)
{
case SLIDER_LINEAR:
constraint.SetTargetLinMotorVelocity(val);
break;
case SLIDER_ANGULAR:
constraint.SetTargetAngMotorVelocity(val);
break;
}
break;
case SLIDER_MAX_MOTOR_FORCE:
switch (linAng)
{
case SLIDER_LINEAR:
constraint.SetMaxLinMotorForce(val);
break;
case SLIDER_ANGULAR:
constraint.SetMaxAngMotorForce(val);
break;
}
break;
}
return true;
}
//BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
public override void SetAngularDamping(BulletBody pBody, float angularDamping)
{

View File

@ -105,7 +105,7 @@ public class BSActorAvatarMove : BSActor
// into the movement motor.
public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
{
m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate()
m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID, "BSActorAvatarMove.setVelocityAndTarget", delegate()
{
if (m_velocityMotor != null)
{
@ -128,6 +128,7 @@ public class BSActorAvatarMove : BSActor
BSMotor.Infinite, // decay time scale
1f // efficiency
);
m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold;
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
@ -278,6 +279,7 @@ public class BSActorAvatarMove : BSActor
if (m_controllingPrim.IsStationary)
{
entprop.Position = m_controllingPrim.RawPosition;
entprop.Velocity = OMV.Vector3.Zero;
m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
}

View File

@ -43,7 +43,9 @@ public enum ConstraintType : int
SLIDER_CONSTRAINT_TYPE,
CONTACT_CONSTRAINT_TYPE,
D6_SPRING_CONSTRAINT_TYPE,
MAX_CONSTRAINT_TYPE
MAX_CONSTRAINT_TYPE, // last type defined by Bullet
//
FIXED_CONSTRAINT_TYPE = 1234 // BulletSim constraint that is fixed and unmoving
}
// ===============================================================================
@ -290,7 +292,7 @@ public enum ConstraintParamAxis : int
AXIS_ANGULAR_X,
AXIS_ANGULAR_Y,
AXIS_ANGULAR_Z,
AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
AXIS_LINEAR_ALL = 20, // added by BulletSim so we don't have to do zillions of calls
AXIS_ANGULAR_ALL,
AXIS_ALL
};
@ -441,6 +443,38 @@ public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float e
public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
public const int HINGE_NOT_SPECIFIED = -1;
public abstract bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation);
public abstract bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse);
public const int SPRING_NOT_SPECIFIED = -1;
public abstract bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint);
public abstract bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss);
public abstract bool SpringSetDamping(BulletConstraint constrain, int index, float damping);
public const int SLIDER_LOWER_LIMIT = 0;
public const int SLIDER_UPPER_LIMIT = 1;
public const int SLIDER_LINEAR = 2;
public const int SLIDER_ANGULAR = 3;
public abstract bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val);
public const int SLIDER_SET_SOFTNESS = 4;
public const int SLIDER_SET_RESTITUTION = 5;
public const int SLIDER_SET_DAMPING = 6;
public const int SLIDER_SET_DIRECTION = 7;
public const int SLIDER_SET_LIMIT = 8;
public const int SLIDER_SET_ORTHO = 9;
public abstract bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
public abstract bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse);
public const int SLIDER_MOTOR_VELOCITY = 10;
public const int SLIDER_MAX_MOTOR_FORCE = 11;
public abstract bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val);
public abstract bool CalculateTransforms(BulletConstraint constrain);
public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
@ -464,6 +498,8 @@ public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
public abstract bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj);
public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);

View File

@ -93,7 +93,7 @@ public sealed class BSCharacter : BSPhysObject
LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
// do actual creation in taint time
PhysScene.TaintedObject("BSCharacter.create", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
{
DetailLog("{0},BSCharacter.create,taint", LocalID);
// New body and shape into PhysBody and PhysShape
@ -121,7 +121,7 @@ public sealed class BSCharacter : BSPhysObject
base.Destroy();
DetailLog("{0},BSCharacter.Destroy", LocalID);
PhysScene.TaintedObject("BSCharacter.destroy", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.destroy", delegate()
{
PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
PhysBody.Clear();
@ -209,7 +209,7 @@ public sealed class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
PhysScene.TaintedObject("BSCharacter.setSize", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
{
if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
{
@ -257,7 +257,7 @@ public sealed class BSCharacter : BSPhysObject
_rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties directly into the physics engine
PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
{
if (PhysBody.HasPhysicalBody)
PhysScene.PE.ClearAllForces(PhysBody);
@ -267,7 +267,7 @@ public sealed class BSCharacter : BSPhysObject
{
_rotationalVelocity = OMV.Vector3.Zero;
PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
{
if (PhysBody.HasPhysicalBody)
{
@ -291,7 +291,7 @@ public sealed class BSCharacter : BSPhysObject
set {
RawPosition = value;
PhysScene.TaintedObject("BSCharacter.setPosition", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setPosition", delegate()
{
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
PositionSanityCheck();
@ -363,7 +363,7 @@ public sealed class BSCharacter : BSPhysObject
{
// The new position value must be pushed into the physics engine but we can't
// just assign to "Position" because of potential call loops.
PhysScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.PositionSanityCheck", delegate()
{
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
ForcePosition = RawPosition;
@ -390,7 +390,7 @@ public sealed class BSCharacter : BSPhysObject
set {
RawForce = value;
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
PhysScene.TaintedObject("BSCharacter.SetForce", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.SetForce", delegate()
{
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
if (PhysBody.HasPhysicalBody)
@ -438,7 +438,7 @@ public sealed class BSCharacter : BSPhysObject
set {
RawVelocity = value;
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
PhysScene.TaintedObject("BSCharacter.setVelocity", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
{
if (m_moveActor != null)
m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
@ -480,7 +480,7 @@ public sealed class BSCharacter : BSPhysObject
if (RawOrientation != value)
{
RawOrientation = value;
PhysScene.TaintedObject("BSCharacter.setOrientation", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setOrientation", delegate()
{
// Bullet assumes we know what we are doing when forcing orientation
// so it lets us go against all the rules and just compensates for them later.
@ -560,7 +560,7 @@ public sealed class BSCharacter : BSPhysObject
public override bool FloatOnWater {
set {
_floatOnWater = value;
PhysScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setFloatOnWater", delegate()
{
if (PhysBody.HasPhysicalBody)
{
@ -588,7 +588,7 @@ public sealed class BSCharacter : BSPhysObject
public override float Buoyancy {
get { return _buoyancy; }
set { _buoyancy = value;
PhysScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
PhysScene.TaintedObject(LocalID, "BSCharacter.setBuoyancy", delegate()
{
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
ForceBuoyancy = _buoyancy;
@ -633,7 +633,7 @@ public sealed class BSCharacter : BSPhysObject
OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
// DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
PhysScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
{
// Bullet adds this central force to the total force for this tick
// DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
@ -676,18 +676,20 @@ public sealed class BSCharacter : BSPhysObject
float heightAdjust = BSParam.AvatarHeightMidFudge;
if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
{
// An avatar is between 1.61 and 2.12 meters. Midpoint is 1.87m.
// The "times 4" relies on the fact that the difference from the midpoint to the extremes is exactly 0.25
float midHeightOffset = size.Z - 1.87f;
const float AVATAR_LOW = 1.1f;
const float AVATAR_MID = 1.775f; // 1.87f
const float AVATAR_HI = 2.45f;
// An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
float midHeightOffset = size.Z - AVATAR_MID;
if (midHeightOffset < 0f)
{
// Small avatar. Add the adjustment based on the distance from midheight
heightAdjust += -1f * midHeightOffset * 4f * BSParam.AvatarHeightLowFudge;
heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
}
else
{
// Large avatar. Add the adjustment based on the distance from midheight
heightAdjust += midHeightOffset * 4f * BSParam.AvatarHeightHighFudge;
heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
}
}
// The total scale height is the central cylindar plus the caps on the two ends.
@ -698,6 +700,9 @@ public sealed class BSCharacter : BSPhysObject
if (newScale.Z < 0)
newScale.Z = 0.1f;
DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
return newScale;
}

View File

@ -64,7 +64,7 @@ public abstract class BSConstraint : IDisposable
{
bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
BSScene.DetailLogZero,
m_body1.ID,
m_body1.ID, m_body1.AddrString,
m_body2.ID, m_body2.AddrString,
success);
@ -77,7 +77,10 @@ public abstract class BSConstraint : IDisposable
{
bool ret = false;
if (m_enabled)
{
m_world.physicsScene.DetailLog("{0},BSConstraint.SetLinearLimits,taint,low={1},high={2}", m_body1.ID, low, high);
ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
}
return ret;
}
@ -86,6 +89,7 @@ public abstract class BSConstraint : IDisposable
bool ret = false;
if (m_enabled)
{
m_world.physicsScene.DetailLog("{0},BSConstraint.SetAngularLimits,taint,low={1},high={2}", m_body1.ID, low, high);
ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
}
return ret;

View File

@ -32,12 +32,19 @@ using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public sealed class BSConstraint6Dof : BSConstraint
public class BSConstraint6Dof : BSConstraint
{
private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2) :base(world)
{
m_body1 = obj1;
m_body2 = obj2;
m_enabled = false;
}
// Create a btGeneric6DofConstraint
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
@ -52,9 +59,11 @@ public sealed class BSConstraint6Dof : BSConstraint
frame2, frame2rot,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
m_enabled = true;
world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
BSScene.DetailLogZero, world.worldID,
PhysicsScene.DetailLog("{0},BS6DofConstraint,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
m_body1.ID, world.worldID,
obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
PhysicsScene.DetailLog("{0},BS6DofConstraint,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
m_body1.ID, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
}
// 6 Dof constraint based on a midpoint between the two constrained bodies
@ -79,9 +88,11 @@ public sealed class BSConstraint6Dof : BSConstraint
m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
joinPoint,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
BSScene.DetailLogZero, world.worldID, m_constraint.AddrString,
m_body1.ID, world.worldID, m_constraint.AddrString,
obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
if (!m_constraint.HasPhysicalConstraint)
{
world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
@ -106,8 +117,10 @@ public sealed class BSConstraint6Dof : BSConstraint
frameInBloc, frameInBrot,
useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
m_enabled = true;
world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString);
PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
m_body1.ID, world.worldID, obj1.ID, obj1.AddrString);
PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed, fBLoc={1},fBRot={2},usefA={3},disCol={4}",
m_body1.ID, frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
}
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* 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 copyrightD
* 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 System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public sealed class BSConstraintConeTwist : BSConstraint
{
public override ConstraintType Type { get { return ConstraintType.CONETWIST_CONSTRAINT_TYPE; } }
public BSConstraintConeTwist(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frameInAloc, Quaternion frameInArot,
Vector3 frameInBloc, Quaternion frameInBrot,
bool disableCollisionsBetweenLinkedBodies)
: base(world)
{
m_body1 = obj1;
m_body2 = obj2;
m_constraint = PhysicsScene.PE.CreateConeTwistConstraint(world, obj1, obj2,
frameInAloc, frameInArot, frameInBloc, frameInBrot,
disableCollisionsBetweenLinkedBodies);
m_enabled = true;
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* 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 copyrightD
* 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 System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public sealed class BSConstraintSlider : BSConstraint
{
public override ConstraintType Type { get { return ConstraintType.SLIDER_CONSTRAINT_TYPE; } }
public BSConstraintSlider(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frameInAloc, Quaternion frameInArot,
Vector3 frameInBloc, Quaternion frameInBrot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
: base(world)
{
m_body1 = obj1;
m_body2 = obj2;
m_constraint = PhysicsScene.PE.CreateSliderConstraint(world, obj1, obj2,
frameInAloc, frameInArot, frameInBloc, frameInBrot,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
m_enabled = true;
}
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* 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 copyrightD
* 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 System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public sealed class BSConstraintSpring : BSConstraint6Dof
{
public override ConstraintType Type { get { return ConstraintType.D6_SPRING_CONSTRAINT_TYPE; } }
public BSConstraintSpring(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frame1Loc, Quaternion frame1Rot,
Vector3 frame2Loc, Quaternion frame2Rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
:base(world, obj1, obj2)
{
m_constraint = PhysicsScene.PE.Create6DofSpringConstraint(world, obj1, obj2,
frame1Loc, frame1Rot, frame2Loc, frame2Rot,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
m_enabled = true;
PhysicsScene.DetailLog("{0},BSConstraintSpring,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
obj1.ID, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
PhysicsScene.DetailLog("{0},BSConstraintSpring,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
m_body1.ID, frame1Loc, frame1Rot, frame2Loc, frame2Rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
}
public bool SetAxisEnable(int pIndex, bool pAxisEnable)
{
PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEnable,obj1ID={1},obj2ID={2},indx={3},enable={4}",
m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pAxisEnable);
PhysicsScene.PE.SpringEnable(m_constraint, pIndex, BSParam.NumericBool(pAxisEnable));
return true;
}
public bool SetStiffness(int pIndex, float pStiffness)
{
PhysicsScene.DetailLog("{0},BSConstraintSpring.SetStiffness,obj1ID={1},obj2ID={2},indx={3},stiff={4}",
m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pStiffness);
PhysicsScene.PE.SpringSetStiffness(m_constraint, pIndex, pStiffness);
return true;
}
public bool SetDamping(int pIndex, float pDamping)
{
PhysicsScene.DetailLog("{0},BSConstraintSpring.SetDamping,obj1ID={1},obj2ID={2},indx={3},damp={4}",
m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pDamping);
PhysicsScene.PE.SpringSetDamping(m_constraint, pIndex, pDamping);
return true;
}
public bool SetEquilibriumPoint(int pIndex, float pEqPoint)
{
PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},indx={3},eqPoint={4}",
m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pEqPoint);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, pIndex, pEqPoint);
return true;
}
public bool SetEquilibriumPoint(Vector3 linearEq, Vector3 angularEq)
{
PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},linearEq={3},angularEq={4}",
m_body1.ID, m_body1.ID, m_body2.ID, linearEq, angularEq);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 0, linearEq.X);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 1, linearEq.Y);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 2, linearEq.Z);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 3, angularEq.X);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 4, angularEq.Y);
PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 5, angularEq.Z);
return true;
}
}
}

View File

@ -77,6 +77,10 @@ public abstract class BSLinkset
{
member = pMember;
}
public virtual void ResetLink() { }
public virtual void SetLinkParameters(BSConstraint constrain) { }
// Returns 'true' if physical property updates from the child should be reported to the simulator
public virtual bool ShouldUpdateChildProperties() { return false; }
}
public LinksetImplementation LinksetImpl { get; protected set; }
@ -148,7 +152,7 @@ public abstract class BSLinkset
// Returns a new linkset for the child which is a linkset of one (just the
// orphened child).
// Called at runtime.
public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child)
public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
{
lock (m_linksetActivityLock)
{
@ -157,7 +161,7 @@ public abstract class BSLinkset
// Cannot remove the root from a linkset.
return this;
}
RemoveChildFromLinkset(child);
RemoveChildFromLinkset(child, inTaintTime);
LinksetMass = ComputeLinksetMass();
}
@ -205,6 +209,17 @@ public abstract class BSLinkset
return ret;
}
public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
{
bool ret = false;
BSLinkInfo found = null;
lock (m_linksetActivityLock)
{
ret = m_children.TryGetValue(child, out found);
}
foundInfo = found;
return ret;
}
// Perform an action on each member of the linkset including root prim.
// Depends on the action on whether this should be done at taint time.
public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
@ -222,6 +237,21 @@ public abstract class BSLinkset
return ret;
}
// Check the type of the link and return 'true' if the link is flexible and the
// updates from the child should be sent to the simulator so things change.
public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
{
bool ret = false;
BSLinkInfo linkInfo;
if (m_children.TryGetValue(child, out linkInfo))
{
ret = linkInfo.ShouldUpdateChildProperties();
}
return ret;
}
// Called after a simulation step to post a collision with this object.
// Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
// anything to add for the collision and it should be passed through normal processing.
@ -255,7 +285,7 @@ public abstract class BSLinkset
// I am the root of a linkset and one of my children is being removed.
// Safe to call even if the child is not really in my linkset.
protected abstract void RemoveChildFromLinkset(BSPrimLinkable child);
protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
// When physical properties are changed the linkset needs to recalculate
// its internal properties.
@ -430,6 +460,13 @@ public abstract class BSLinkset
return com;
}
#region Extension
public virtual object Extension(string pFunct, params object[] pParams)
{
return null;
}
#endregion // Extension
// Invoke the detailed logger and output something if it's enabled.
protected void DetailLog(string msg, params Object[] args)
{

View File

@ -90,10 +90,9 @@ public sealed class BSLinksetCompound : BSLinkset
// its internal properties.
public override void Refresh(BSPrimLinkable requestor)
{
base.Refresh(requestor);
// Something changed so do the rebuilding thing
// ScheduleRebuild();
ScheduleRebuild(requestor);
base.Refresh(requestor);
}
// Schedule a refresh to happen after all the other taint processing.
@ -127,7 +126,7 @@ public sealed class BSLinksetCompound : BSLinkset
if (IsRoot(child))
{
// The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return ret;
}
@ -144,7 +143,7 @@ public sealed class BSLinksetCompound : BSLinkset
if (IsRoot(child))
{
// Schedule a rebuild to verify that the root shape is set to the real shape.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return ret;
}
@ -227,7 +226,7 @@ public sealed class BSLinksetCompound : BSLinkset
// there will already be a rebuild scheduled.
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
updated.LocalID, whichUpdated);
ScheduleRebuild(updated);
Refresh(updated);
}
}
}
@ -242,10 +241,10 @@ public sealed class BSLinksetCompound : BSLinkset
{
bool ret = false;
DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
ScheduleRebuild(child);
Refresh(child);
return ret;
}
@ -263,14 +262,14 @@ public sealed class BSLinksetCompound : BSLinkset
DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
// Rebuild the compound shape with the new child shape included
ScheduleRebuild(child);
Refresh(child);
}
return;
}
// Remove the specified child from the linkset.
// Safe to call even if the child is not really in the linkset.
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
{
child.ClearDisplacement();
@ -282,17 +281,17 @@ public sealed class BSLinksetCompound : BSLinkset
child.LocalID, child.PhysBody.AddrString);
// Cause the child's body to be rebuilt and thus restored to normal operation
child.ForceBodyShapeRebuild(false);
child.ForceBodyShapeRebuild(inTaintTime);
if (!HasAnyChildren)
{
// The linkset is now empty. The root needs rebuilding.
LinksetRoot.ForceBodyShapeRebuild(false);
LinksetRoot.ForceBodyShapeRebuild(inTaintTime);
}
else
{
// Rebuild the compound shape with the child removed
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
}
return;
@ -318,10 +317,10 @@ public sealed class BSLinksetCompound : BSLinkset
// being destructed and going non-physical.
LinksetRoot.ForceBodyShapeRebuild(true);
// There is no reason to build all this physical stuff for a non-physical linkset.
if (!LinksetRoot.IsPhysicallyActive)
// There is no reason to build all this physical stuff for a non-physical or empty linkset.
if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
{
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
return; // Note the 'finally' clause at the botton which will get executed.
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -28,6 +28,8 @@ using System;
using System.Collections.Generic;
using System.Text;
using OpenSim.Region.OptionalModules.Scripting;
using OMV = OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
@ -51,18 +53,32 @@ public sealed class BSLinksetConstraints : BSLinkset
public float cfm;
public float erp;
public float solverIterations;
//
public OMV.Vector3 frameInAloc;
public OMV.Quaternion frameInArot;
public OMV.Vector3 frameInBloc;
public OMV.Quaternion frameInBrot;
public bool useLinearReferenceFrameA;
// Spring
public bool[] springAxisEnable;
public float[] springDamping;
public float[] springStiffness;
public OMV.Vector3 springLinearEquilibriumPoint;
public OMV.Vector3 springAngularEquilibriumPoint;
public BSLinkInfoConstraint(BSPrimLinkable pMember)
: base(pMember)
{
constraint = null;
ResetToFixedConstraint();
ResetLink();
member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
}
// Set all the parameters for this constraint to a fixed, non-movable constraint.
public void ResetToFixedConstraint()
public override void ResetLink()
{
constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
// constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
constraintType = ConstraintType.FIXED_CONSTRAINT_TYPE;
linearLimitLow = OMV.Vector3.Zero;
linearLimitHigh = OMV.Vector3.Zero;
angularLimitLow = OMV.Vector3.Zero;
@ -74,17 +90,37 @@ public sealed class BSLinksetConstraints : BSLinkset
cfm = BSParam.LinkConstraintCFM;
erp = BSParam.LinkConstraintERP;
solverIterations = BSParam.LinkConstraintSolverIterations;
frameInAloc = OMV.Vector3.Zero;
frameInArot = OMV.Quaternion.Identity;
frameInBloc = OMV.Vector3.Zero;
frameInBrot = OMV.Quaternion.Identity;
useLinearReferenceFrameA = true;
springAxisEnable = new bool[6];
springDamping = new float[6];
springStiffness = new float[6];
for (int ii = 0; ii < springAxisEnable.Length; ii++)
{
springAxisEnable[ii] = false;
springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
}
springLinearEquilibriumPoint = OMV.Vector3.Zero;
springAngularEquilibriumPoint = OMV.Vector3.Zero;
member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
}
// Given a constraint, apply the current constraint parameters to same.
public void SetConstraintParameters(BSConstraint constrain)
public override void SetLinkParameters(BSConstraint constrain)
{
member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
switch (constraintType)
{
case ConstraintType.FIXED_CONSTRAINT_TYPE:
case ConstraintType.D6_CONSTRAINT_TYPE:
BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
if (constrain6dof != null)
{
// NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
// zero linear and angular limits makes the objects unable to move in relation to each other
constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
@ -99,10 +135,55 @@ public sealed class BSLinksetConstraints : BSLinkset
}
}
break;
case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
if (constrainSpring != null)
{
// zero linear and angular limits makes the objects unable to move in relation to each other
constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
// tweek the constraint to increase stability
constrainSpring.UseFrameOffset(useFrameOffset);
constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
constrainSpring.SetCFMAndERP(cfm, erp);
if (solverIterations != 0f)
{
constrainSpring.SetSolverIterations(solverIterations);
}
for (int ii = 0; ii < springAxisEnable.Length; ii++)
{
constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
constrainSpring.SetDamping(ii, springDamping[ii]);
if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
constrainSpring.SetStiffness(ii, springStiffness[ii]);
}
constrainSpring.CalculateTransforms();
if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
else
constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
}
break;
default:
break;
}
}
// Return 'true' if the property updates from the physics engine should be reported
// to the simulator.
// If the constraint is fixed, we don't need to report as the simulator and viewer will
// report the right things.
public override bool ShouldUpdateChildProperties()
{
bool ret = true;
if (constraintType == ConstraintType.FIXED_CONSTRAINT_TYPE)
ret = false;
return ret;
}
}
public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
@ -110,12 +191,15 @@ public sealed class BSLinksetConstraints : BSLinkset
LinksetImpl = LinksetImplementation.Constraint;
}
private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
// When physical properties are changed the linkset needs to recalculate
// its internal properties.
// This is queued in the 'post taint' queue so the
// refresh will happen once after all the other taints are applied.
public override void Refresh(BSPrimLinkable requestor)
{
ScheduleRebuild(requestor);
base.Refresh(requestor);
}
@ -134,7 +218,13 @@ public sealed class BSLinksetConstraints : BSLinkset
m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
{
if (HasAnyChildren)
{
// Constraints that have not been changed are not rebuild but make sure
// the constraint of the requestor is rebuilt.
PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
// Rebuild the linkset and all its constraints.
RecomputeLinksetConstraints();
}
});
}
}
@ -152,7 +242,7 @@ public sealed class BSLinksetConstraints : BSLinkset
if (IsRoot(child))
{
// The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return ret;
}
@ -171,7 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset
if (IsRoot(child))
{
// Schedule a rebuild to verify that the root shape is set to the real shape.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return ret;
}
@ -199,7 +289,7 @@ public sealed class BSLinksetConstraints : BSLinkset
// Just undo all the constraints for this linkset. Rebuild at the end of the step.
ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
// Cause the constraints, et al to be rebuilt before the next simulation step.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return ret;
}
@ -217,14 +307,14 @@ public sealed class BSLinksetConstraints : BSLinkset
DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
// Cause constraints and assorted properties to be recomputed before the next simulation step.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
return;
}
// Remove the specified child from the linkset.
// Safe to call even if the child is not really in my linkset.
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
{
if (m_children.Remove(child))
{
@ -236,12 +326,12 @@ public sealed class BSLinksetConstraints : BSLinkset
rootx.LocalID, rootx.PhysBody.AddrString,
childx.LocalID, childx.PhysBody.AddrString);
m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
{
PhysicallyUnlinkAChildFromRoot(rootx, childx);
});
// See that the linkset parameters are recomputed at the end of the taint time.
ScheduleRebuild(LinksetRoot);
Refresh(LinksetRoot);
}
else
{
@ -262,8 +352,8 @@ public sealed class BSLinksetConstraints : BSLinkset
// Create a static constraint between the two passed objects
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
{
BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint;
if (liConstraint == null)
BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
if (linkInfo == null)
return null;
// Zero motion for children so they don't interpolate
@ -271,27 +361,26 @@ public sealed class BSLinksetConstraints : BSLinkset
BSConstraint constrain = null;
switch (liConstraint.constraintType)
switch (linkInfo.constraintType)
{
case ConstraintType.FIXED_CONSTRAINT_TYPE:
case ConstraintType.D6_CONSTRAINT_TYPE:
// Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of li.member
OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position;
OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
// real world coordinate of midpoint between the two objects
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
rootPrim.LocalID,
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
rootPrim.Position, liConstraint.member.Position, midPoint);
DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
rootPrim.Position, linkInfo.member.Position, midPoint);
// create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
constrain = new BSConstraint6Dof(
m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true );
m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@ -319,12 +408,24 @@ public sealed class BSLinksetConstraints : BSLinkset
// ==================================================================================
*/
break;
case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
linkInfo.useLinearReferenceFrameA,
true /*disableCollisionsBetweenLinkedBodies*/);
DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
rootPrim.LocalID,
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
rootPrim.Position, linkInfo.member.Position);
break;
default:
break;
}
liConstraint.SetConstraintParameters(constrain);
linkInfo.SetLinkParameters(constrain);
m_physicsScene.Constraints.AddConstraint(constrain);
@ -343,6 +444,14 @@ public sealed class BSLinksetConstraints : BSLinkset
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
childPrim.LocalID, childPrim.PhysBody.AddrString);
// If asked to unlink root from root, just remove all the constraints
if (rootPrim == childPrim || childPrim == LinksetRoot)
{
PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
ret = true;
}
else
{
// Find the constraint for this link and get rid of it from the overall collection and from my list
if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
{
@ -350,6 +459,7 @@ public sealed class BSLinksetConstraints : BSLinkset
m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
ret = true;
}
}
return ret;
}
@ -382,9 +492,9 @@ public sealed class BSLinksetConstraints : BSLinkset
Rebuilding = true;
// There is no reason to build all this physical stuff for a non-physical linkset.
if (!LinksetRoot.IsPhysicallyActive)
if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
{
DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
return; // Note the 'finally' clause at the botton which will get executed.
}
@ -401,6 +511,7 @@ public sealed class BSLinksetConstraints : BSLinkset
// If constraint doesn't exist yet, create it.
constrain = BuildConstraint(LinksetRoot, li);
}
li.SetLinkParameters(constrain);
constrain.RecomputeConstraintVariables(linksetMass);
// PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
@ -412,5 +523,324 @@ public sealed class BSLinksetConstraints : BSLinkset
Rebuilding = false;
}
}
#region Extension
public override object Extension(string pFunct, params object[] pParams)
{
object ret = null;
switch (pFunct)
{
// pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
case ExtendedPhysics.PhysFunctChangeLinkType:
if (pParams.Length > 2)
{
int requestedType = (int)pParams[2];
DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
if (requestedType == (int)ConstraintType.FIXED_CONSTRAINT_TYPE
|| requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
|| requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
|| requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
|| requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
|| requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
{
BSPrimLinkable child = pParams[1] as BSPrimLinkable;
if (child != null)
{
DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
{
// Pick up all the constraints currently created.
RemoveDependencies(child);
BSLinkInfo linkInfo = null;
if (TryGetLinkInfo(child, out linkInfo))
{
BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
if (linkInfoC != null)
{
linkInfoC.constraintType = (ConstraintType)requestedType;
ret = (object)true;
DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
}
else
{
DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
}
}
else
{
DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
}
// Cause the whole linkset to be rebuilt in post-taint time.
Refresh(child);
});
}
else
{
DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
}
}
else
{
DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
}
}
break;
// pParams = [ BSPhysObject root, BSPhysObject child ]
case ExtendedPhysics.PhysFunctGetLinkType:
if (pParams.Length > 0)
{
BSPrimLinkable child = pParams[1] as BSPrimLinkable;
if (child != null)
{
BSLinkInfo linkInfo = null;
if (TryGetLinkInfo(child, out linkInfo))
{
BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
if (linkInfoC != null)
{
ret = (object)(int)linkInfoC.constraintType;
DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
}
}
}
}
break;
// pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
case ExtendedPhysics.PhysFunctChangeLinkParams:
// There should be two parameters: the childActor and a list of parameters to set
if (pParams.Length > 2)
{
BSPrimLinkable child = pParams[1] as BSPrimLinkable;
BSLinkInfo baseLinkInfo = null;
if (TryGetLinkInfo(child, out baseLinkInfo))
{
BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
if (linkInfo != null)
{
int valueInt;
float valueFloat;
bool valueBool;
OMV.Vector3 valueVector;
OMV.Vector3 valueVector2;
OMV.Quaternion valueQuaternion;
int axisLow, axisHigh;
int opIndex = 2;
while (opIndex < pParams.Length)
{
int thisOp = 0;
string errMsg = "";
try
{
thisOp = (int)pParams[opIndex];
DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
switch (thisOp)
{
case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
valueInt = (int)pParams[opIndex + 1];
ConstraintType valueType = (ConstraintType)valueInt;
if (valueType == ConstraintType.FIXED_CONSTRAINT_TYPE
|| valueType == ConstraintType.D6_CONSTRAINT_TYPE
|| valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
|| valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
|| valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
|| valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
{
linkInfo.constraintType = valueType;
}
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.frameInAloc = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
linkInfo.frameInArot = valueQuaternion;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.frameInBloc = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
linkInfo.frameInBrot = valueQuaternion;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.linearLimitLow = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.linearLimitHigh = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.angularLimitLow = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
linkInfo.angularLimitHigh = valueVector;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
valueBool = ((int)pParams[opIndex + 1]) != 0;
linkInfo.useFrameOffset = valueBool;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
valueBool = ((int)pParams[opIndex + 1]) != 0;
linkInfo.enableTransMotor = valueBool;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
valueFloat = (float)pParams[opIndex + 1];
linkInfo.transMotorMaxVel = valueFloat;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
valueFloat = (float)pParams[opIndex + 1];
linkInfo.transMotorMaxForce = valueFloat;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_CFM:
errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
valueFloat = (float)pParams[opIndex + 1];
linkInfo.cfm = valueFloat;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_ERP:
errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
valueFloat = (float)pParams[opIndex + 1];
linkInfo.erp = valueFloat;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
valueFloat = (float)pParams[opIndex + 1];
linkInfo.solverIterations = valueFloat;
opIndex += 2;
break;
case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
valueInt = (int)pParams[opIndex + 1];
valueBool = ((int)pParams[opIndex + 2]) != 0;
GetAxisRange(valueInt, out axisLow, out axisHigh);
for (int ii = axisLow; ii <= axisHigh; ii++)
linkInfo.springAxisEnable[ii] = valueBool;
opIndex += 3;
break;
case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
valueInt = (int)pParams[opIndex + 1];
valueFloat = (float)pParams[opIndex + 2];
GetAxisRange(valueInt, out axisLow, out axisHigh);
for (int ii = axisLow; ii <= axisHigh; ii++)
linkInfo.springDamping[ii] = valueFloat;
opIndex += 3;
break;
case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
valueInt = (int)pParams[opIndex + 1];
valueFloat = (float)pParams[opIndex + 2];
GetAxisRange(valueInt, out axisLow, out axisHigh);
for (int ii = axisLow; ii <= axisHigh; ii++)
linkInfo.springStiffness[ii] = valueFloat;
opIndex += 3;
break;
case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
valueVector = (OMV.Vector3)pParams[opIndex + 1];
valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
linkInfo.springLinearEquilibriumPoint = valueVector;
linkInfo.springAngularEquilibriumPoint = valueVector2;
opIndex += 3;
break;
case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
valueBool = ((int)pParams[opIndex + 1]) != 0;
linkInfo.useLinearReferenceFrameA = valueBool;
opIndex += 2;
break;
default:
break;
}
}
catch (InvalidCastException e)
{
m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
LogHeader, errMsg, e);
}
catch (Exception e)
{
m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
}
}
}
// Something changed so a rebuild is in order
Refresh(child);
}
}
break;
default:
ret = base.Extension(pFunct, pParams);
break;
}
return ret;
}
// Bullet constraints keep some limit parameters for each linear and angular axis.
// Setting same is easier if there is an easy way to see all or types.
// This routine returns the array limits for the set of axis.
private void GetAxisRange(int rangeSpec, out int low, out int high)
{
switch (rangeSpec)
{
case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
low = 0;
high = 2;
break;
case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
low = 3;
high = 5;
break;
case ExtendedPhysics.PHYS_AXIS_ALL:
low = 0;
high = 5;
break;
default:
low = high = rangeSpec;
break;
}
return;
}
#endregion // Extension
}
}

View File

@ -134,6 +134,7 @@ public static class BSParam
public static float AvatarHeightMidFudge { get; private set; }
public static float AvatarHeightHighFudge { get; private set; }
public static float AvatarContactProcessingThreshold { get; private set; }
public static float AvatarStopZeroThreshold { get; private set; }
public static int AvatarJumpFrames { get; private set; }
public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
public static float AvatarStepHeight { get; private set; }
@ -570,11 +571,13 @@ public static class BSParam
new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
-0.2f ),
new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
0.2f ),
0.1f ),
new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
0.2f ),
0.1f ),
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
0.1f ),
new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped",
0.1f ),
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
1.0f ),
new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
@ -683,21 +686,21 @@ public static class BSParam
0f ),
new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
100f ),
200f ),
new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
2f ),
10f ),
new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
0.1f ),
20f ),
new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
0f ),
0.1f ),
new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
100f ),
10f ),
new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
false ),
true ),
new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
false ),
true ),
new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
false ),
true ),
new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
false ),
@ -826,7 +829,7 @@ public static class BSParam
private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
{
BSScene physScene = pPhysScene;
physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate()
physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetConstraintSolver", delegate()
{
physScene.PE.ResetConstraintSolver(physScene.World);
});

View File

@ -121,7 +121,7 @@ public abstract class BSPhysObject : PhysicsActor
public virtual void Destroy()
{
PhysicalActors.Enable(false);
PhysScene.TaintedObject("BSPhysObject.Destroy", delegate()
PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
{
PhysicalActors.Dispose();
});
@ -300,9 +300,20 @@ public abstract class BSPhysObject : PhysicsActor
// Called in taint-time!!
public void ActivateIfPhysical(bool forceIt)
{
if (IsPhysical && PhysBody.HasPhysicalBody)
if (PhysBody.HasPhysicalBody)
{
if (IsPhysical)
{
// Physical objects might need activating
PhysScene.PE.Activate(PhysBody, forceIt);
}
else
{
// Clear the collision cache since we've changed some properties.
PhysScene.PE.ClearCollisionProxyCache(PhysScene.World, PhysBody);
}
}
}
// 'actors' act on the physical object to change or constrain its motion. These can range from
// hovering to complex vehicle motion.
@ -509,7 +520,7 @@ public abstract class BSPhysObject : PhysicsActor
// make sure first collision happens
NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
{
if (PhysBody.HasPhysicalBody)
CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
@ -524,7 +535,7 @@ public abstract class BSPhysObject : PhysicsActor
public override void UnSubscribeEvents() {
// DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
SubscribedEventsMs = 0;
PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
{
// Make sure there is a body there because sometimes destruction happens in an un-ideal order.
if (PhysBody.HasPhysicalBody)

View File

@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
[Serializable]
public class BSPrim : BSPhysObject
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS PRIM]";
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
@ -102,7 +102,7 @@ public class BSPrim : BSPhysObject
// DetailLog("{0},BSPrim.constructor,call", LocalID);
// do the actual object creation at taint time
PhysScene.TaintedObject("BSPrim.create", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
{
// Make sure the object is being created with some sanity.
ExtremeSanityCheck(true /* inTaintTime */);
@ -126,7 +126,7 @@ public class BSPrim : BSPhysObject
// Undo any vehicle properties
this.VehicleType = (int)Vehicle.TYPE_NONE;
PhysScene.TaintedObject("BSPrim.Destroy", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate()
{
DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
// If there are physical body and shape, release my use of same.
@ -161,7 +161,7 @@ public class BSPrim : BSPhysObject
}
public override bool ForceBodyShapeRebuild(bool inTaintTime)
{
PhysScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate()
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
@ -178,7 +178,7 @@ public class BSPrim : BSPhysObject
if (value != _isSelected)
{
_isSelected = value;
PhysScene.TaintedObject("BSPrim.setSelected", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate()
{
DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
SetObjectDynamic(false);
@ -224,7 +224,7 @@ public class BSPrim : BSPhysObject
_rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties in the physics engine
PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
{
if (PhysBody.HasPhysicalBody)
PhysScene.PE.ClearAllForces(PhysBody);
@ -234,7 +234,7 @@ public class BSPrim : BSPhysObject
{
_rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties in the physics engine
PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
{
// DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
if (PhysBody.HasPhysicalBody)
@ -262,7 +262,7 @@ public class BSPrim : BSPhysObject
});
// Update parameters so the new actor's Refresh() action is called at the right time.
PhysScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
{
UpdatePhysicalParameters();
});
@ -287,7 +287,7 @@ public class BSPrim : BSPhysObject
RawPosition = value;
PositionSanityCheck(false);
PhysScene.TaintedObject("BSPrim.setPosition", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate()
{
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
ForcePosition = RawPosition;
@ -531,7 +531,7 @@ public class BSPrim : BSPhysObject
set {
Vehicle type = (Vehicle)value;
PhysScene.TaintedObject("setVehicleType", delegate()
PhysScene.TaintedObject(LocalID, "setVehicleType", delegate()
{
// Some vehicle scripts change vehicle type on the fly as an easy way to
// change all the parameters. Like a plane changing to CAR when on the
@ -561,7 +561,7 @@ public class BSPrim : BSPhysObject
}
public override void VehicleFloatParam(int param, float value)
{
PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate()
{
BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
if (vehicleActor != null)
@ -573,7 +573,7 @@ public class BSPrim : BSPhysObject
}
public override void VehicleVectorParam(int param, OMV.Vector3 value)
{
PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate()
{
BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
if (vehicleActor != null)
@ -585,7 +585,7 @@ public class BSPrim : BSPhysObject
}
public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
{
PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate()
{
BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
if (vehicleActor != null)
@ -597,7 +597,7 @@ public class BSPrim : BSPhysObject
}
public override void VehicleFlags(int param, bool remove)
{
PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate()
{
BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
if (vehicleActor != null)
@ -613,7 +613,7 @@ public class BSPrim : BSPhysObject
if (_isVolumeDetect != newValue)
{
_isVolumeDetect = newValue;
PhysScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate()
{
// DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
SetObjectDynamic(true);
@ -628,7 +628,7 @@ public class BSPrim : BSPhysObject
public override void SetMaterial(int material)
{
base.SetMaterial(material);
PhysScene.TaintedObject("BSPrim.SetMaterial", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate()
{
UpdatePhysicalParameters();
});
@ -641,7 +641,7 @@ public class BSPrim : BSPhysObject
if (base.Friction != value)
{
base.Friction = value;
PhysScene.TaintedObject("BSPrim.setFriction", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate()
{
UpdatePhysicalParameters();
});
@ -656,7 +656,7 @@ public class BSPrim : BSPhysObject
if (base.Restitution != value)
{
base.Restitution = value;
PhysScene.TaintedObject("BSPrim.setRestitution", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate()
{
UpdatePhysicalParameters();
});
@ -673,7 +673,7 @@ public class BSPrim : BSPhysObject
if (base.Density != value)
{
base.Density = value;
PhysScene.TaintedObject("BSPrim.setDensity", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate()
{
UpdatePhysicalParameters();
});
@ -688,7 +688,7 @@ public class BSPrim : BSPhysObject
if (base.GravModifier != value)
{
base.GravModifier = value;
PhysScene.TaintedObject("BSPrim.setGravityModifier", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate()
{
UpdatePhysicalParameters();
});
@ -699,7 +699,7 @@ public class BSPrim : BSPhysObject
get { return RawVelocity; }
set {
RawVelocity = value;
PhysScene.TaintedObject("BSPrim.setVelocity", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate()
{
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
ForceVelocity = RawVelocity;
@ -745,7 +745,7 @@ public class BSPrim : BSPhysObject
return;
RawOrientation = value;
PhysScene.TaintedObject("BSPrim.setOrientation", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate()
{
ForceOrientation = RawOrientation;
});
@ -776,7 +776,7 @@ public class BSPrim : BSPhysObject
if (_isPhysical != value)
{
_isPhysical = value;
PhysScene.TaintedObject("BSPrim.setIsPhysical", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate()
{
DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
SetObjectDynamic(true);
@ -1020,7 +1020,7 @@ public class BSPrim : BSPhysObject
public override bool FloatOnWater {
set {
_floatOnWater = value;
PhysScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate()
{
if (_floatOnWater)
CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
@ -1037,7 +1037,7 @@ public class BSPrim : BSPhysObject
_rotationalVelocity = value;
Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
PhysScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate()
{
ForceRotationalVelocity = _rotationalVelocity;
});
@ -1068,7 +1068,7 @@ public class BSPrim : BSPhysObject
get { return _buoyancy; }
set {
_buoyancy = value;
PhysScene.TaintedObject("BSPrim.setBuoyancy", delegate()
PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate()
{
ForceBuoyancy = _buoyancy;
});
@ -1142,7 +1142,7 @@ public class BSPrim : BSPhysObject
// DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
OMV.Vector3 addForce = force;
PhysScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate()
{
// Bullet adds this central force to the total force for this tick.
// Deep down in Bullet:
@ -1172,7 +1172,7 @@ public class BSPrim : BSPhysObject
OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
// DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
PhysScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate()
{
// Bullet adds this impulse immediately to the velocity
DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
@ -1197,7 +1197,7 @@ public class BSPrim : BSPhysObject
if (force.IsFinite())
{
OMV.Vector3 angForce = force;
PhysScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate()
{
if (PhysBody.HasPhysicalBody)
{
@ -1221,7 +1221,7 @@ public class BSPrim : BSPhysObject
public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
{
OMV.Vector3 applyImpulse = impulse;
PhysScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate()
{
if (PhysBody.HasPhysicalBody)
{
@ -1552,39 +1552,10 @@ public class BSPrim : BSPhysObject
#region Extension
public override object Extension(string pFunct, params object[] pParams)
{
DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct);
object ret = null;
switch (pFunct)
{
case BSScene.PhysFunctGetLinksetType:
{
BSPrimLinkable myHandle = this as BSPrimLinkable;
if (myHandle != null)
{
ret = (object)myHandle.LinksetType;
}
m_log.DebugFormat("{0} Extension.physGetLinksetType, type={1}", LogHeader, ret);
break;
}
case BSScene.PhysFunctSetLinksetType:
{
if (pParams.Length > 0)
{
BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[0];
BSPrimLinkable myHandle = this as BSPrimLinkable;
if (myHandle != null && myHandle.Linkset.IsRoot(myHandle))
{
PhysScene.TaintedObject("BSPrim.PhysFunctSetLinksetType", delegate()
{
// Cause the linkset type to change
m_log.DebugFormat("{0} Extension.physSetLinksetType, oldType={1}, newType={2}",
LogHeader, myHandle.Linkset.LinksetImpl, linksetType);
myHandle.ConvertLinkset(linksetType);
});
}
ret = (object)(int)linksetType;
}
break;
}
default:
ret = base.Extension(pFunct, pParams);
break;

View File

@ -30,6 +30,7 @@ using System.Linq;
using System.Text;
using OpenSim.Framework;
using OpenSim.Region.OptionalModules.Scripting;
using OMV = OpenMetaverse;
@ -41,6 +42,8 @@ public class BSPrimLinkable : BSPrimDisplaced
// operations necessary for keeping the linkset created and, additionally, this
// calls the linkset implementation for its creation and management.
private static readonly string LogHeader = "[BULLETS PRIMLINKABLE]";
// This adds the overrides for link() and delink() so the prim is linkable.
public BSLinkset Linkset { get; set; }
@ -58,15 +61,12 @@ public class BSPrimLinkable : BSPrimDisplaced
Linkset = BSLinkset.Factory(PhysScene, this);
PhysScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate()
{
Linkset.Refresh(this);
});
}
public override void Destroy()
{
Linkset = Linkset.RemoveMeFromLinkset(this);
Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */);
base.Destroy();
}
@ -80,7 +80,7 @@ public class BSPrimLinkable : BSPrimDisplaced
Linkset = parent.Linkset.AddMeToLinkset(this);
DetailLog("{0},BSPrimLinkset.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
DetailLog("{0},BSPrimLinkable.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
}
return;
@ -94,9 +94,9 @@ public class BSPrimLinkable : BSPrimDisplaced
BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
int childrenBefore = Linkset.NumberOfChildren; // DEBUG
Linkset = Linkset.RemoveMeFromLinkset(this);
Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/);
DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
DetailLog("{0},BSPrimLinkable.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
return;
}
@ -108,7 +108,7 @@ public class BSPrimLinkable : BSPrimDisplaced
set
{
base.Position = value;
PhysScene.TaintedObject("BSPrimLinkset.setPosition", delegate()
PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setPosition", delegate()
{
Linkset.UpdateProperties(UpdatedProperties.Position, this);
});
@ -122,7 +122,7 @@ public class BSPrimLinkable : BSPrimDisplaced
set
{
base.Orientation = value;
PhysScene.TaintedObject("BSPrimLinkset.setOrientation", delegate()
PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setOrientation", delegate()
{
Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
});
@ -180,7 +180,7 @@ public class BSPrimLinkable : BSPrimDisplaced
// Do any filtering/modification needed for linksets.
public override void UpdateProperties(EntityProperties entprop)
{
if (Linkset.IsRoot(this))
if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this))
{
// Properties are only updated for the roots of a linkset.
// TODO: this will have to change when linksets are articulated.
@ -240,6 +240,8 @@ public class BSPrimLinkable : BSPrimDisplaced
bool ret = false;
if (LinksetType != newType)
{
DetailLog("{0},BSPrimLinkable.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType);
// Set the implementation type first so the call to BSLinkset.Factory gets the new type.
this.LinksetType = newType;
@ -263,7 +265,10 @@ public class BSPrimLinkable : BSPrimDisplaced
// Remove the children from the old linkset and add to the new (will be a new instance from the factory)
foreach (BSPrimLinkable child in children)
{
oldLinkset.RemoveMeFromLinkset(child);
oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/);
}
foreach (BSPrimLinkable child in children)
{
newLinkset.AddMeToLinkset(child);
child.Linkset = newLinkset;
}
@ -274,5 +279,70 @@ public class BSPrimLinkable : BSPrimDisplaced
}
return ret;
}
#region Extension
public override object Extension(string pFunct, params object[] pParams)
{
DetailLog("{0} BSPrimLinkable.Extension,op={1},nParam={2}", LocalID, pFunct, pParams.Length);
object ret = null;
switch (pFunct)
{
// physGetLinksetType();
// pParams = [ BSPhysObject root, null ]
case ExtendedPhysics.PhysFunctGetLinksetType:
{
ret = (object)LinksetType;
DetailLog("{0},BSPrimLinkable.Extension.physGetLinksetType,type={1}", LocalID, ret);
break;
}
// physSetLinksetType(type);
// pParams = [ BSPhysObject root, null, integer type ]
case ExtendedPhysics.PhysFunctSetLinksetType:
{
if (pParams.Length > 2)
{
BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[2];
if (Linkset.IsRoot(this))
{
PhysScene.TaintedObject(LocalID, "BSPrim.PhysFunctSetLinksetType", delegate()
{
// Cause the linkset type to change
DetailLog("{0},BSPrimLinkable.Extension.physSetLinksetType, oldType={1},newType={2}",
LocalID, Linkset.LinksetImpl, linksetType);
ConvertLinkset(linksetType);
});
}
ret = (object)(int)linksetType;
}
break;
}
// physChangeLinkType(linknum, typeCode);
// pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
case ExtendedPhysics.PhysFunctChangeLinkType:
{
ret = Linkset.Extension(pFunct, pParams);
break;
}
// physGetLinkType(linknum);
// pParams = [ BSPhysObject root, BSPhysObject child ]
case ExtendedPhysics.PhysFunctGetLinkType:
{
ret = Linkset.Extension(pFunct, pParams);
break;
}
// physChangeLinkParams(linknum, [code, value, code, value, ...]);
// pParams = [ BSPhysObject root, BSPhysObject child, object[] [ string op, object opParam, string op, object opParam, ... ] ]
case ExtendedPhysics.PhysFunctChangeLinkParams:
{
ret = Linkset.Extension(pFunct, pParams);
break;
}
default:
ret = base.Extension(pFunct, pParams);
break;
}
return ret;
}
#endregion // Extension
}
}

View File

@ -157,12 +157,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public delegate void TaintCallback();
private struct TaintCallbackEntry
{
public String originator;
public String ident;
public TaintCallback callback;
public TaintCallbackEntry(string i, TaintCallback c)
public TaintCallbackEntry(string pIdent, TaintCallback pCallBack)
{
ident = i;
callback = c;
originator = BSScene.DetailLogZero;
ident = pIdent;
callback = pCallBack;
}
public TaintCallbackEntry(string pOrigin, string pIdent, TaintCallback pCallBack)
{
originator = pOrigin;
ident = pIdent;
callback = pCallBack;
}
}
private Object _taintLock = new Object(); // lock for using the next object
@ -867,18 +875,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public override bool IsThreaded { get { return false; } }
#region Extensions
// =============================================================
// Per scene functions. See below.
// Per avatar functions. See BSCharacter.
// Per prim functions. See BSPrim.
public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
// =============================================================
public override object Extension(string pFunct, params object[] pParams)
{
DetailLog("{0} BSScene.Extension,op={1}", DetailLogZero, pFunct);
return base.Extension(pFunct, pParams);
}
#endregion // Extensions
@ -897,26 +896,37 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Calls to the PhysicsActors can't directly call into the physics engine
// because it might be busy. We delay changes to a known time.
// We rely on C#'s closure to save and restore the context for the delegate.
public void TaintedObject(String ident, TaintCallback callback)
public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback)
{
TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback);
}
public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback)
{
TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
}
public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback)
{
TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback);
}
public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback)
{
TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
}
// Sometimes a potentially tainted operation can be used in and out of taint time.
// This routine executes the command immediately if in taint-time otherwise it is queued.
public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback)
{
if (!m_initialized) return;
if (inTaintTime)
pCallback();
else
{
lock (_taintLock)
{
_taintOperations.Add(new TaintCallbackEntry(ident, callback));
_taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
}
return;
}
// Sometimes a potentially tainted operation can be used in and out of taint time.
// This routine executes the command immediately if in taint-time otherwise it is queued.
public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
{
if (inTaintTime)
callback();
else
TaintedObject(ident, callback);
}
private void TriggerPreStepEvent(float timeStep)
@ -960,7 +970,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{
try
{
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG
tcbe.callback();
}
catch (Exception e)
@ -977,10 +987,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// will replace any previous operation by the same object.
public void PostTaintObject(String ident, uint ID, TaintCallback callback)
{
string uniqueIdent = ident + "-" + ID.ToString();
string IDAsString = ID.ToString();
string uniqueIdent = ident + "-" + IDAsString;
lock (_taintLock)
{
_postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback);
_postTaintOperations[uniqueIdent] = new TaintCallbackEntry(IDAsString, uniqueIdent, callback);
}
return;
@ -1090,7 +1101,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
string xval = val;
List<uint> xlIDs = lIDs;
string xparm = parm;
TaintedObject("BSScene.UpdateParameterSet", delegate() {
TaintedObject(DetailLogZero, "BSScene.UpdateParameterSet", delegate() {
BSParam.ParameterDefnBase thisParam;
if (BSParam.TryGetParameter(xparm, out thisParam))
{

View File

@ -8974,7 +8974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
case ScriptBaseClass.PRIM_TYPE_SCULPT:
res.Add(Shape.SculptTexture.ToString());
res.Add(new LSL_String(Shape.SculptTexture.ToString()));
res.Add(new LSL_Integer(Shape.SculptType));
break;
@ -9316,7 +9316,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
));
break;
case (int)ScriptBaseClass.PRIM_LINK_TARGET:
if(remain < 3)
// TODO: Should be issuing a runtime script warning in this case.
if (remain < 2)
return null;
return rules.GetSublist(idx, -1);

View File

@ -3043,7 +3043,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
sp.ControllingClient.Kick(alert);
// ...and close on our side
sp.Scene.IncomingCloseAgent(sp.UUID, false);
sp.Scene.CloseAgent(sp.UUID, false);
}
});
}

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* 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 System.Collections.Generic;
using System.Reflection;
using System.Text;
using log4net;
using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Assets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
using OpenSim.Region.OptionalModules.World.NPC;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.Instance;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
namespace OpenSim.Region.ScriptEngine.Shared.Tests
{
[TestFixture]
public class LSL_ApiObjectTests : OpenSimTestCase
{
private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
private const float FLOAT_ACCURACY = 0.00005f;
protected Scene m_scene;
protected XEngine.XEngine m_engine;
[SetUp]
public override void SetUp()
{
base.SetUp();
IConfigSource initConfigSource = new IniConfigSource();
IConfig config = initConfigSource.AddConfig("XEngine");
config.Set("Enabled", "true");
m_scene = new SceneHelpers().SetupScene();
SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
m_engine = new XEngine.XEngine();
m_engine.Initialise(initConfigSource);
m_engine.AddRegion(m_scene);
}
[Test]
public void TestllGetLinkPrimitiveParams()
{
TestHelpers.InMethod();
TestHelpers.EnableLogging();
UUID ownerId = TestHelpers.ParseTail(0x1);
SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
grp1.AbsolutePosition = new Vector3(10, 11, 12);
m_scene.AddSceneObject(grp1);
LSL_Api apiGrp1 = new LSL_Api();
apiGrp1.Initialize(m_engine, grp1.RootPart, null, null);
// Check simple 1 prim case
{
LSL_List resList
= apiGrp1.llGetLinkPrimitiveParams(1, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
Assert.That(resList.Length, Is.EqualTo(1));
}
// Check 2 prim case
{
LSL_List resList
= apiGrp1.llGetLinkPrimitiveParams(
1,
new LSL_List(
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
new LSL_Integer(2),
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
Assert.That(resList.Length, Is.EqualTo(2));
}
// Check invalid parameters are ignored
{
LSL_List resList
= apiGrp1.llGetLinkPrimitiveParams(3, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
Assert.That(resList.Length, Is.EqualTo(0));
}
// Check all parameters are ignored if an initial bad link is given
{
LSL_List resList
= apiGrp1.llGetLinkPrimitiveParams(
3,
new LSL_List(
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
new LSL_Integer(1),
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
Assert.That(resList.Length, Is.EqualTo(0));
}
// Check only subsequent parameters are ignored when we hit the first bad link number
{
LSL_List resList
= apiGrp1.llGetLinkPrimitiveParams(
1,
new LSL_List(
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
new LSL_Integer(3),
new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
Assert.That(resList.Length, Is.EqualTo(1));
}
}
[Test]
// llSetPrimitiveParams and llGetPrimitiveParams test.
public void TestllSetPrimitiveParams()
{
TestHelpers.InMethod();
// Create Prim1.
Scene scene = new SceneHelpers().SetupScene();
string obj1Name = "Prim1";
UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
SceneObjectPart part1 =
new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
Vector3.Zero, Quaternion.Identity,
Vector3.Zero) { Name = obj1Name, UUID = objUuid };
Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
LSL_Api apiGrp1 = new LSL_Api();
apiGrp1.Initialize(m_engine, part1, null, null);
// Note that prim hollow check is passed with the other prim params in order to allow the
// specification of a different check value from the prim param. A cylinder, prism, sphere,
// torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
// specifies a value of 95% and checks to see if 70% was properly returned.
// Test a sphere.
CheckllSetPrimitiveParams(
apiGrp1,
"test 1", // Prim test identification string
new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
0.80f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
0.80f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
apiGrp1,
"test 2", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.90f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.90f); // Prim hollow check
// Test a box.
CheckllSetPrimitiveParams(
apiGrp1,
"test 3", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95f, // Prim hollow
new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.95f); // Prim hollow check
// Test a tube.
CheckllSetPrimitiveParams(
apiGrp1,
"test 4", // Prim test identification string
new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.00f, // Prim hollow
new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
// Expression for y selected to test precision problems during byte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
1.11f, // Prim revolutions
0.88f, // Prim radius
0.95f, // Prim skew
0.00f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
apiGrp1,
"test 5", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95f, // Prim hollow
// Expression for x selected to test precision problems during sbyte
// cast in SetPrimitiveShapeBlockParams.
new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.70f); // Prim hollow check
// Test a sculpted prim.
CheckllSetPrimitiveParams(
apiGrp1,
"test 6", // Prim test identification string
new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
"be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
}
// Set prim params for a box, cylinder or prism and check results.
public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
float primHollowCheck)
{
// Set the prim params.
api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primTaper, primShear));
// Get params for prim to validate settings.
LSL_Types.list primParams =
api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 6), primTest + " prim taper");
CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
}
// Set prim params for a sphere and check results.
public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
{
// Set the prim params.
api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primDimple));
// Get params for prim to validate settings.
LSL_Types.list primParams =
api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primDimple, api.llList2Vector(primParams, 6), primTest + " prim dimple");
}
// Set prim params for a torus, tube or ring and check results.
public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
float primRev, float primRadius, float primSkew, float primHollowCheck)
{
// Set the prim params.
api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
primTaper, primRev, primRadius, primSkew));
// Get params for prim to validate settings.
LSL_Types.list primParams =
api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Valdate settings.
CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primHoleSize, api.llList2Vector(primParams, 6), primTest + " prim hole size");
CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
CheckllSetPrimitiveParamsVector(primProfCut, api.llList2Vector(primParams, 8), primTest + " prim profile cut");
CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 9), primTest + " prim taper");
Assert.AreEqual(primRev, api.llList2Float(primParams, 10), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
Assert.AreEqual(primRadius, api.llList2Float(primParams, 11), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim radius fail");
Assert.AreEqual(primSkew, api.llList2Float(primParams, 12), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim skew fail");
}
// Set prim params for a sculpted prim and check results.
public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
{
// Set the prim params.
api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
// Get params for prim to validate settings.
LSL_Types.list primParams =
api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primMap, (string)api.llList2String(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim map check fail");
Assert.AreEqual(primSculptType, api.llList2Integer(primParams, 3),
"TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
}
public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
{
// Check each vector component against expected result.
Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on x component");
Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on y component");
Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on z component");
}
}
}

View File

@ -47,9 +47,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
[TestFixture, LongRunning]
public class LSL_ApiTest
{
private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
private const float FLOAT_ACCURACY = 0.00005f;
private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
private LSL_Api m_lslApi;
[SetUp]
@ -254,241 +253,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
Assert.AreEqual(0.0, check.z, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Z bounds check fail");
}
[Test]
// llSetPrimitiveParams and llGetPrimitiveParams test.
public void TestllSetPrimitiveParams()
{
TestHelpers.InMethod();
// Create Prim1.
Scene scene = new SceneHelpers().SetupScene();
string obj1Name = "Prim1";
UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
SceneObjectPart part1 =
new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
Vector3.Zero, Quaternion.Identity,
Vector3.Zero) { Name = obj1Name, UUID = objUuid };
Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
// Note that prim hollow check is passed with the other prim params in order to allow the
// specification of a different check value from the prim param. A cylinder, prism, sphere,
// torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
// specifies a value of 95% and checks to see if 70% was properly returned.
// Test a sphere.
CheckllSetPrimitiveParams(
"test 1", // Prim test identification string
new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
0.80f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
0.80f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
"test 2", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.90f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.90f); // Prim hollow check
// Test a box.
CheckllSetPrimitiveParams(
"test 3", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95f, // Prim hollow
new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.95f); // Prim hollow check
// Test a tube.
CheckllSetPrimitiveParams(
"test 4", // Prim test identification string
new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.00f, // Prim hollow
new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
// Expression for y selected to test precision problems during byte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
1.11f, // Prim revolutions
0.88f, // Prim radius
0.95f, // Prim skew
0.00f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
"test 5", // Prim test identification string
new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95f, // Prim hollow
// Expression for x selected to test precision problems during sbyte
// cast in SetPrimitiveShapeBlockParams.
new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.70f); // Prim hollow check
// Test a sculpted prim.
CheckllSetPrimitiveParams(
"test 6", // Prim test identification string
new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
"be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
}
// Set prim params for a box, cylinder or prism and check results.
public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
float primHollowCheck)
{
// Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primTaper, primShear));
// Get params for prim to validate settings.
LSL_Types.list primParams =
m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 6), primTest + " prim taper");
CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
}
// Set prim params for a sphere and check results.
public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
{
// Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primDimple));
// Get params for prim to validate settings.
LSL_Types.list primParams =
m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primDimple, m_lslApi.llList2Vector(primParams, 6), primTest + " prim dimple");
}
// Set prim params for a torus, tube or ring and check results.
public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
float primRev, float primRadius, float primSkew, float primHollowCheck)
{
// Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
primTaper, primRev, primRadius, primSkew));
// Get params for prim to validate settings.
LSL_Types.list primParams =
m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Valdate settings.
CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
CheckllSetPrimitiveParamsVector(primHoleSize, m_lslApi.llList2Vector(primParams, 6), primTest + " prim hole size");
CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim radius fail");
Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim skew fail");
}
// Set prim params for a sculpted prim and check results.
public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
{
// Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
// Get params for prim to validate settings.
LSL_Types.list primParams =
m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
// Validate settings.
CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
"TestllSetPrimitiveParams " + primTest + " prim type check fail");
Assert.AreEqual(primMap, (string)m_lslApi.llList2String(primParams, 2),
"TestllSetPrimitiveParams " + primTest + " prim map check fail");
Assert.AreEqual(primSculptType, m_lslApi.llList2Integer(primParams, 3),
"TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
}
public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
{
// Check each vector component against expected result.
Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on x component");
Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on y component");
Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
"TestllSetPrimitiveParams " + msg + " vector check fail on z component");
}
[Test]
public void TestllVecNorm()
{

View File

@ -84,7 +84,7 @@ namespace OpenSim.Tests.Common
TestClient neighbourTc = new TestClient(newAgent, neighbourScene);
neighbourTcs.Add(neighbourTc);
neighbourScene.AddNewClient(neighbourTc, PresenceType.User);
neighbourScene.AddNewAgent(neighbourTc, PresenceType.User);
};
}
@ -119,7 +119,7 @@ namespace OpenSim.Tests.Common
TestClient destinationClient = new TestClient(newAgent, destinationScene);
destinationClients.Add(destinationClient);
destinationScene.AddNewClient(destinationClient, PresenceType.User);
destinationScene.AddNewAgent(destinationClient, PresenceType.User);
ThreadPool.UnsafeQueueUserWorkItem(o => destinationClient.CompleteMovement(), null);
};

View File

@ -548,7 +548,7 @@ namespace OpenSim.Tests.Common
Console.WriteLine("NewUserConnection failed: " + reason);
// Stage 2: add the new client as a child agent to the scene
scene.AddNewClient(client, PresenceType.User);
scene.AddNewAgent(client, PresenceType.User);
return scene.GetScenePresence(client.AgentId);
}

View File

@ -414,8 +414,8 @@
;# {SMTP_SERVER_PASSWORD} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server password} {}
; SMTP_SERVER_PASSWORD = ""
[Network]
[Network]
;# {ConsoleUser} {} {User name for console account} {}
;; Configure the remote console user here. This will not actually be used
;; unless you use -console=rest at startup.
@ -452,6 +452,7 @@
;; web server
; user_agent = "OpenSim LSL (Mozilla Compatible)"
[XMLRPC]
;# {XmlRpcRouterModule} {} {Module used to route incoming llRemoteData calls} {XmlRpcRouterModule XmlRpcGridRouterModule} XmlRpcRouterModule
;; If enabled and set to XmlRpcRouterModule, this will post an event,
@ -466,9 +467,6 @@
;# {XmlRpcPort} {} {Port for incoming llRemoteData xmlrpc calls} {} 20800
;XmlRpcPort = 20800
;; {option} {depends on} {question to ask} {choices} default value
;# {XmlRpcHubURI} {XmlRpcRouterModule} {URI for external service used to register xmlrpc channels created in the simulator. This depends on XmlRpcRouterModule being set to XmlRpcGridRouterModule} {} http://example.com
;; If XmlRpcRouterModule is set to XmlRpcGridRouterModule, the simulator
;; will use this address to register xmlrpc channels on the external
@ -512,7 +510,6 @@
[SimulatorFeatures]
;# {MapImageServerURI} {} {URL for the map server} {}
; Experimental new information sent in SimulatorFeatures cap for Kokua
; viewers
@ -1016,6 +1013,7 @@
; XmlRpcServiceReadKey = 1234
; XmlRpcServiceWriteKey = 1234
[InterestManagement]
;# {UpdatePrioritizationScheme} {} {Update prioritization scheme?} {BestAvatarResponsiveness Time Distance SimpleAngularDistance FrontBack} BestAvatarResponsiveness
;; This section controls how state updates are prioritized for each client
@ -1034,16 +1032,19 @@
;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} false
; Enabled = false
[Terrain]
;# {InitialTerrain} {} {Initial terrain type} {pinhead-island flat} pinhead-island
; InitialTerrain = "pinhead-island"
[UserProfiles]
;# {ProfileURL} {} {Set url to UserProfilesService} {}
;; Set the value of the url to your UserProfilesService
;; If un-set / "" the module is disabled
;; ProfileServiceURL = http://127.0.0.1:8002
[Architecture]
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,

View File

@ -399,7 +399,6 @@
; ProfileURL = http://127.0.0.1:9000
[SMTP]
enabled = false
@ -461,6 +460,7 @@
; many simultaneous requests, default is 30 and is currently applied only to assets
;MaxRequestConcurrency = 30
[ClientStack.LindenUDP]
; Set this to true to process incoming packets asynchronously. Networking is
; already separated from packet handling with a queue, so this will only
@ -560,6 +560,7 @@
;
;PausedAckTimeout = 300
[ClientStack.LindenCaps]
;; Long list of capabilities taken from
;; http://wiki.secondlife.com/wiki/Current_Sim_Capabilities
@ -636,7 +637,6 @@
Cap_AvatarPickerSearch = "localhost"
[Chat]
; Controls whether the chat module is enabled. Default is true.
enabled = true;
@ -652,9 +652,21 @@
[EntityTransfer]
; The maximum distance in regions that an agent is allowed to teleport along the x or y axis
; This is set to 4095 because current viewers can't handle teleports that are greater than this distance
max_distance = 4095
; The maximum protocol version that we will use for outgoing transfers
; Valid values are
; "SIMULATION/0.2"
; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
; - this protocol is more efficient than "SIMULATION/0.1"
; "SIMULATION/0.1"
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
MaxOutgoingTransferVersion = "SIMULATION/0.2"
; The maximum distance in regions that an agent is allowed to teleport
; along the x or y axis. This is set to 16383 because current viewers
; can't handle teleports that are greater than this distance
; Setting to 0 will allow teleports of any distance
;
max_distance = 16383
; Minimum user level required for HyperGrid teleports
LevelHGTeleport = 0
@ -953,6 +965,7 @@
; Default is false.
;force_simple_prim_meshing = true
[BulletSim]
; All the BulletSim parameters can be displayed with the console command
; "physics get all" and all are defined in the source file
@ -1268,6 +1281,7 @@
; Maximum number of external urls that scripts can set up in this simulator (e.g. via llRequestURL())
max_external_urls_per_simulator = 100
[DataSnapshot]
; The following set of configs pertains to search.
; Set index_sims to true to enable search engines to index your searchable data
@ -1672,17 +1686,19 @@
RootReprioritizationDistance = 10.0
ChildReprioritizationDistance = 20.0
[Monitoring]
; Enable region monitoring
; If true, this will print out an error if more than a minute has passed since the last simulator frame
; Also is another source of region statistics provided via the regionstats URL
Enabled = true
[WebStats]
; View region statistics via a web page
; See http://opensimulator.org/wiki/FAQ#Region_Statistics_on_a_Web_Page
; Use a web browser and type in the "Login URI" + "/SStats/"
; For example- http://127.0.0.1:9000/SStats/
[WebStats]
; enabled=false
@ -1690,13 +1706,16 @@
; Enable media on a prim facilities
Enabled = true;
[NPC]
;; Enable Non Player Character (NPC) facilities
Enabled = false
[Terrain]
InitialTerrain = "pinhead-island"
;;
;; If you are using a simian grid frontend you can enable
;; this module to upload tile images for the mapping fn
@ -1706,6 +1725,7 @@
MaptileURL = "http://www.mygrid.com/Grid/"
RefreshTime = 3600
;;
;; JsonStore module provides structured store for scripts
;;
@ -1716,6 +1736,7 @@ Enabled = False
EnableObjectStore = False
MaxStringSpace = 0
;;
;; These are defaults that are overwritten below in [Architecture].
;; These defaults allow OpenSim to work out of the box with
@ -1729,14 +1750,17 @@ MaxStringSpace = 0
; asset store each time the region starts
AssetLoaderEnabled = true
[GridService]
;; default standalone, overridable in StandaloneCommon.ini
StorageProvider = "OpenSim.Data.Null.dll:NullRegionData"
[AutoBackupModule]
;; 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
@ -1744,9 +1768,11 @@ MaxStringSpace = 0
;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
MaxDistance = 100.0
[ServiceThrottle]
;; Default time interval (in ms) for the throttle service thread to wake up
Interval = 5000
[Modules]
Include-modules = "addon-modules/*/config/*.ini"

View File

@ -64,5 +64,6 @@
[MapImageService]
LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector"
; in minutes
RefreshTime = 60

View File

@ -206,7 +206,6 @@
; Example:
; Region_Test_1 = "DisallowForeigners"
;; Uncomment if you are using SimianGrid for grid services
[SimianGrid]
;; SimianGrid services URL

View File

@ -35,6 +35,17 @@
SimulationServiceInConnector = true
LibraryModule = true
[SimulationService]
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
; It is used to control the teleport handoff process.
; Valid values are
; "SIMULATION/0.2"
; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
; - this protocol is more efficient than "SIMULATION/0.1"
; "SIMULATION/0.1"
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
ConnectorProtocolVersion = "SIMULATION/0.2"
[Profile]
Module = "BasicProfileModule"
@ -85,5 +96,6 @@
[MapImageService]
LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector"
; in minutes
RefreshTime = 60

View File

@ -91,6 +91,7 @@
; accessible from other grids
;
ProfileServerURI = "http://mygridserver.com:8002/user"
;; If you want to protect your assets from being copied by foreign visitors
;; uncomment the next line. You may want to do this on sims that have licensed content.
; OutboundPermission = False

View File

@ -118,6 +118,7 @@
[MapImageService]
LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService"
; in minutes
RefreshTime = 60

View File

@ -47,7 +47,6 @@
;; This is a default that can be overwritten in some sections.
; GatekeeperURI = "http://127.0.0.1:9000"
[Modules]
;; Choose one cache module and the corresponding config file, if it exists.
;; Copy the config .example file into your own .ini file and alter that
@ -385,5 +384,3 @@
UserAccountService = OpenSim.Services.UserAccountService.dll:UserAccountService
AuthenticationServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"

View File

@ -38,6 +38,16 @@
SimulationServiceInConnector = true
MapImageServiceInConnector = true
[SimulationService]
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
; It is used to control the teleport handoff process.
; Valid values are
; "SIMULATION/0.2"
; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
; - this protocol is more efficient than "SIMULATION/0.1"
; "SIMULATION/0.1"
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
ConnectorProtocolVersion = "SIMULATION/0.2"
[Messaging]
MessageTransferModule = HGMessageTransferModule

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1920,6 +1920,7 @@
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.OptionalModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.Meshing" path="../../../../bin/Physics/"/>