Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a14221754 | ||
|
|
d5a3139b05 | ||
|
|
6f5fd067a5 | ||
|
|
9fcf1de0fa | ||
|
|
86c39d618e | ||
|
|
068f22a52c | ||
|
|
726b7dce61 | ||
|
|
d260e398f5 | ||
|
|
560ea54c98 | ||
|
|
10152815ac | ||
|
|
1217785155 | ||
|
|
712bee7206 | ||
|
|
568ff6fddc | ||
|
|
b6568c7e22 | ||
|
|
4179d8f651 | ||
|
|
bde8ac6a5c | ||
|
|
9d04c6a828 | ||
|
|
7a9eb26b00 | ||
|
|
2e32b2aacb | ||
|
|
6ade1c6c76 | ||
|
|
0e4a06edf9 | ||
|
|
d3efb6a7f7 | ||
|
|
70438ff6ab | ||
|
|
1b021e0eaa | ||
|
|
21a046e622 | ||
|
|
1f740926a2 | ||
|
|
fd3e267ec6 | ||
|
|
73a62788a5 | ||
|
|
1076f56373 | ||
|
|
0dd47d88de | ||
|
|
34ae7afe1a | ||
|
|
826f8ce791 | ||
|
|
05ff4379f0 | ||
|
|
3ffad76b0d | ||
|
|
1a8a6b95e5 | ||
|
|
785171109e | ||
|
|
87aedc44a0 | ||
|
|
ee86b460cb | ||
|
|
0acde92af9 | ||
|
|
719380380a | ||
|
|
a9dcdae6a2 | ||
|
|
e2b7d941b6 | ||
|
|
aa4479c4bc | ||
|
|
8568503921 | ||
|
|
6f1ff47fee | ||
|
|
514c58bc96 | ||
|
|
cfdb2700bc | ||
|
|
cfef2b19bb | ||
|
|
2a7b4c9db9 | ||
|
|
7284cb76b6 | ||
|
|
a4f7eb5b4d | ||
|
|
1e64549acf | ||
|
|
6570f5dcfe | ||
|
|
90907bf4fd | ||
|
|
dbbc260d1a | ||
|
|
49228f9855 | ||
|
|
8b7bcc8346 | ||
|
|
3f8a99937e | ||
|
|
b92128b715 | ||
|
|
6eb1436c55 | ||
|
|
41b33b6f0f | ||
|
|
e05d11faa5 | ||
|
|
803fa36b68 | ||
|
|
902c1f0009 | ||
|
|
b21f261008 | ||
|
|
ab1c63b20c | ||
|
|
5c35aa560e | ||
|
|
63be8e3596 | ||
|
|
62b12783df | ||
|
|
935888d6da | ||
|
|
2e7f7c41a7 | ||
|
|
ed0ffae151 | ||
|
|
ea5bab5107 |
@@ -623,10 +623,13 @@ namespace OpenSim.Groups
|
||||
if (agent != null)
|
||||
break;
|
||||
}
|
||||
if (agent == null) // oops
|
||||
return AgentID.ToString();
|
||||
if (agent != null)
|
||||
return Util.ProduceUserUniversalIdentifier(agent);
|
||||
|
||||
// we don't know anything about this foreign user
|
||||
// try asking the user management module, which may know more
|
||||
return m_UserManagement.GetUserUUI(AgentID);
|
||||
|
||||
return Util.ProduceUserUniversalIdentifier(agent);
|
||||
}
|
||||
|
||||
private string AgentUUIForOutside(string AgentIDStr)
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace OpenSim.Data
|
||||
bool Delete(UUID regionID);
|
||||
|
||||
List<RegionData> GetDefaultRegions(UUID scopeID);
|
||||
List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
|
||||
List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
|
||||
List<RegionData> GetHyperlinks(UUID scopeID);
|
||||
}
|
||||
|
||||
@@ -315,6 +315,11 @@ namespace OpenSim.Data.MSSQL
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -310,6 +310,11 @@ namespace OpenSim.Data.MySQL
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -239,6 +239,11 @@ namespace OpenSim.Data.Null
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
if (cmd[3] == "start")
|
||||
{
|
||||
Start();
|
||||
con.OutputFormat("Now recording all stats very {0}ms to file", m_statsLogIntervalMs);
|
||||
con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
|
||||
}
|
||||
else if (cmd[3] == "stop")
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace OpenSim.Framework
|
||||
NoMove = 64, // Don't allow moving this region
|
||||
Reservation = 128, // This is an inactive reservation
|
||||
Authenticate = 256, // Require authentication
|
||||
Hyperlink = 512 // Record represents a HG link
|
||||
Hyperlink = 512, // Record represents a HG link
|
||||
DefaultHGRegion = 1024 // Record represents a default region for hypergrid teleports only.
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ namespace OpenSim.Framework
|
||||
private static SmartThreadPool m_ThreadPool;
|
||||
|
||||
// Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
|
||||
private static readonly DateTime unixEpoch =
|
||||
public static readonly DateTime UnixEpoch =
|
||||
DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
|
||||
|
||||
private static readonly string rawUUIDPattern
|
||||
@@ -521,20 +521,18 @@ namespace OpenSim.Framework
|
||||
|
||||
public static int ToUnixTime(DateTime stamp)
|
||||
{
|
||||
TimeSpan t = stamp.ToUniversalTime() - unixEpoch;
|
||||
return (int) t.TotalSeconds;
|
||||
TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
|
||||
return (int)t.TotalSeconds;
|
||||
}
|
||||
|
||||
public static DateTime ToDateTime(ulong seconds)
|
||||
{
|
||||
DateTime epoch = unixEpoch;
|
||||
return epoch.AddSeconds(seconds);
|
||||
return UnixEpoch.AddSeconds(seconds);
|
||||
}
|
||||
|
||||
public static DateTime ToDateTime(int seconds)
|
||||
{
|
||||
DateTime epoch = unixEpoch;
|
||||
return epoch.AddSeconds(seconds);
|
||||
return UnixEpoch.AddSeconds(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddForClient()
|
||||
public void TestAddForClient()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
@@ -88,7 +88,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveForClient()
|
||||
public void TestRemoveForClient()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
public List<UUID> folders;
|
||||
}
|
||||
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
|
||||
|
||||
foreach (Thread t in m_workerThreads)
|
||||
Watchdog.AbortThread(t.ManagedThreadId);
|
||||
Watchdog.AbortThread(t.ManagedThreadId);
|
||||
|
||||
m_scene = null;
|
||||
}
|
||||
@@ -296,36 +296,49 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
|
||||
|
||||
lock (responses)
|
||||
responses[requestID] = response;
|
||||
responses[requestID] = response;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
args.Type = PollServiceEventArgs.EventType.Inventory;
|
||||
// Register this as a poll service
|
||||
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)
|
||||
|
||||
@@ -326,15 +326,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
|
||||
UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
|
||||
string message, ChatSourceType src, bool ignoreDistance)
|
||||
{
|
||||
Vector3 fromRegionPos = fromPos + regionPos;
|
||||
Vector3 toRegionPos = presence.AbsolutePosition +
|
||||
new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
|
||||
presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
|
||||
int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
|
||||
if (presence.LifecycleState != ScenePresenceState.Running)
|
||||
return false;
|
||||
|
||||
if (!ignoreDistance)
|
||||
{
|
||||
Vector3 fromRegionPos = fromPos + regionPos;
|
||||
Vector3 toRegionPos = presence.AbsolutePosition +
|
||||
new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
|
||||
presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
|
||||
int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
|
||||
|
||||
if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
|
||||
type == ChatTypeEnum.Say && dis > m_saydistance ||
|
||||
type == ChatTypeEnum.Shout && dis > m_shoutdistance)
|
||||
|
||||
@@ -536,7 +536,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message);
|
||||
m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,6 +518,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}",
|
||||
@@ -832,8 +835,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||
|
||||
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
|
||||
return;
|
||||
@@ -920,6 +923,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
||||
{
|
||||
if (!sp.Scene.IncomingPreCloseAgent(sp))
|
||||
return;
|
||||
|
||||
// We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
|
||||
// they regard the new region as the current region after receiving the AgentMovementComplete
|
||||
// response. If close is sent before then, it will cause the viewer to quit instead.
|
||||
@@ -1053,8 +1059,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||
|
||||
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
|
||||
return;
|
||||
@@ -1082,6 +1088,9 @@ 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))
|
||||
return;
|
||||
|
||||
// RED ALERT!!!!
|
||||
// PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
|
||||
// THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
|
||||
@@ -1095,6 +1104,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
// then this will be handled in IncomingCloseAgent under lock conditions
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
|
||||
|
||||
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -481,14 +484,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
|
||||
public string GetUserUUI(UUID userID)
|
||||
{
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
|
||||
if (account != null)
|
||||
return userID.ToString();
|
||||
|
||||
UserData ud;
|
||||
lock (m_UserCache)
|
||||
m_UserCache.TryGetValue(userID, out ud);
|
||||
|
||||
if (ud == null) // It's not in the cache
|
||||
{
|
||||
string[] names = new string[2];
|
||||
// This will pull the data from either UserAccounts or GridUser
|
||||
// and stick it into the cache
|
||||
TryGetUserNamesFromServices(userID, names);
|
||||
lock (m_UserCache)
|
||||
m_UserCache.TryGetValue(userID, out ud);
|
||||
}
|
||||
|
||||
if (ud != null)
|
||||
{
|
||||
string homeURL = ud.HomeURL;
|
||||
@@ -533,7 +542,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
AddUser(uuid, homeURL + ";" + first + " " + last);
|
||||
}
|
||||
|
||||
public void AddUser (UUID id, string creatorData)
|
||||
public void AddUser(UUID id, string creatorData)
|
||||
{
|
||||
//m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
|
||||
|
||||
@@ -543,24 +552,24 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
|
||||
if (oldUser != null)
|
||||
{
|
||||
if (creatorData == null || creatorData == String.Empty)
|
||||
{
|
||||
//ignore updates without creator data
|
||||
return;
|
||||
}
|
||||
|
||||
//try update unknown users, but don't update anyone else
|
||||
if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown"))
|
||||
{
|
||||
lock (m_UserCache)
|
||||
m_UserCache.Remove(id);
|
||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (creatorData == null || creatorData == String.Empty)
|
||||
// {
|
||||
// //ignore updates without creator data
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// //try update unknown users, but don't update anyone else
|
||||
// if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown"))
|
||||
// {
|
||||
// lock (m_UserCache)
|
||||
// m_UserCache.Remove(id);
|
||||
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
//we have already a valid user within the cache
|
||||
return;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id);
|
||||
@@ -593,20 +602,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||
user.LastName = "@unknown";
|
||||
}
|
||||
}
|
||||
|
||||
if (parts.Length >= 2)
|
||||
user.FirstName = parts[1].Replace(' ', '.');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Temporarily add unknown user entries of this type into the cache so that we can distinguish
|
||||
// this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding
|
||||
// TODO: Can be removed when GUN* unknown users have definitely dropped significantly or
|
||||
// disappeared.
|
||||
user.FirstName = "Unknown";
|
||||
user.LastName = "UserUMMAU4";
|
||||
|
||||
AddUserInternal(user);
|
||||
}
|
||||
|
||||
AddUserInternal(user);
|
||||
// To avoid issues with clients, particularly Hypergrid ones, permanently caching
|
||||
// UUID -> "Unknown User" name bindings, elsewhere we will drop such requests rather than replying.
|
||||
// This also means that we cannot add an unknown user binding to the cache here.
|
||||
// else
|
||||
// {
|
||||
// // Temporarily add unknown user entries of this type into the cache so that we can distinguish
|
||||
// // this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding
|
||||
// // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or
|
||||
// // disappeared.
|
||||
// user.FirstName = "Unknown";
|
||||
// user.LastName = "UserUMMAU4";
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
return m_GridService.GetDefaultRegions(scopeID);
|
||||
}
|
||||
|
||||
public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return m_GridService.GetDefaultHypergridRegions(scopeID);
|
||||
}
|
||||
|
||||
public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
return m_GridService.GetFallbackRegions(scopeID, x, y);
|
||||
|
||||
@@ -277,6 +277,26 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
return rinfo;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
List<GridRegion> rinfo = m_LocalGridService.GetDefaultHypergridRegions(scopeID);
|
||||
//m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetDefaultHypergridRegions {0} found {1} regions", name, rinfo.Count);
|
||||
List<GridRegion> grinfo = m_RemoteGridService.GetDefaultHypergridRegions(scopeID);
|
||||
|
||||
if (grinfo != null)
|
||||
{
|
||||
//m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultHypergridRegions {0} found {1} regions", name, grinfo.Count);
|
||||
foreach (GridRegion r in grinfo)
|
||||
{
|
||||
m_RegionInfoCache.Cache(r);
|
||||
if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
|
||||
rinfo.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
return rinfo;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y);
|
||||
|
||||
@@ -46,8 +46,8 @@ namespace OpenSim.Region.CoreModules.World.Region
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
|
||||
public class RestartModule : INonSharedRegionModule, IRestartModule
|
||||
{
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected Scene m_Scene;
|
||||
protected Timer m_CountdownTimer = null;
|
||||
@@ -203,18 +203,30 @@ namespace OpenSim.Region.CoreModules.World.Region
|
||||
|
||||
public void SetTimer(int intervalSeconds)
|
||||
{
|
||||
m_CountdownTimer = new Timer();
|
||||
m_CountdownTimer.AutoReset = false;
|
||||
m_CountdownTimer.Interval = intervalSeconds * 1000;
|
||||
m_CountdownTimer.Elapsed += OnTimer;
|
||||
m_CountdownTimer.Start();
|
||||
if (intervalSeconds > 0)
|
||||
{
|
||||
m_CountdownTimer = new Timer();
|
||||
m_CountdownTimer.AutoReset = false;
|
||||
m_CountdownTimer.Interval = intervalSeconds * 1000;
|
||||
m_CountdownTimer.Elapsed += OnTimer;
|
||||
m_CountdownTimer.Start();
|
||||
}
|
||||
else if (m_CountdownTimer != null)
|
||||
{
|
||||
m_CountdownTimer.Stop();
|
||||
m_CountdownTimer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
|
||||
intervalSeconds, m_Scene.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTimer(object source, ElapsedEventArgs e)
|
||||
{
|
||||
int nextInterval = DoOneNotice();
|
||||
|
||||
SetTimer(nextInterval);
|
||||
SetTimer(DoOneNotice());
|
||||
}
|
||||
|
||||
public void AbortRestart(string message)
|
||||
|
||||
@@ -512,6 +512,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);
|
||||
}
|
||||
|
||||
@@ -3695,10 +3695,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
// We need to ensure that we are not already removing the scene presence before we ask it not to be
|
||||
// closed.
|
||||
if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running)
|
||||
if (sp != null && sp.IsChildAgent
|
||||
&& (sp.LifecycleState == ScenePresenceState.Running
|
||||
|| sp.LifecycleState == ScenePresenceState.PreRemove))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name);
|
||||
"[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
|
||||
sp.Name, sp.LifecycleState, Name);
|
||||
|
||||
// In the case where, for example, an A B C D region layout, an avatar may
|
||||
// teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
|
||||
@@ -3720,6 +3723,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// }
|
||||
// else if (EntityTransferModule.IsInTransit(sp.UUID))
|
||||
|
||||
sp.LifecycleState = ScenePresenceState.Running;
|
||||
|
||||
if (EntityTransferModule.IsInTransit(sp.UUID))
|
||||
{
|
||||
sp.DoNotCloseAfterTeleport = true;
|
||||
@@ -3824,7 +3829,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
try
|
||||
{
|
||||
if (!AuthorizeUser(acd, SeeIntoRegion, out reason))
|
||||
if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
|
||||
{
|
||||
m_authenticateHandler.RemoveCircuit(acd.circuitcode);
|
||||
return false;
|
||||
@@ -3855,6 +3860,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// Let the SP know how we got here. This has a lot of interesting
|
||||
// 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)
|
||||
{
|
||||
@@ -4346,10 +4364,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
|
||||
if (childAgentUpdate != null)
|
||||
{
|
||||
if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
|
||||
// Only warn for now
|
||||
m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
|
||||
childAgentUpdate.UUID, cAgentData.SessionID);
|
||||
// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
|
||||
// // Only warn for now
|
||||
// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
|
||||
// childAgentUpdate.UUID, cAgentData.SessionID);
|
||||
|
||||
// I can't imagine *yet* why we would get an update if the agent is a root agent..
|
||||
// however to avoid a race condition crossing borders..
|
||||
@@ -4440,6 +4458,50 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell a single agent 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().
|
||||
/// </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)
|
||||
{
|
||||
lock (m_removeClientLock)
|
||||
{
|
||||
// We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
|
||||
// teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
|
||||
// want to obey this close since C may have renewed the child agent lease on B.
|
||||
if (sp.DoNotCloseAfterTeleport)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
|
||||
sp.IsChildAgent ? "child" : "root", sp.Name, Name);
|
||||
|
||||
// Need to reset the flag so that a subsequent close after another teleport can succeed.
|
||||
sp.DoNotCloseAfterTeleport = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sp.LifecycleState != ScenePresenceState.Running)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
|
||||
sp.Name, Name, sp.LifecycleState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
sp.LifecycleState = ScenePresenceState.PreRemove;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell a single agent to disconnect from the region.
|
||||
/// </summary>
|
||||
@@ -4459,16 +4521,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
if (sp == null)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}",
|
||||
"[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
|
||||
agentID, Name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sp.LifecycleState != ScenePresenceState.Running)
|
||||
if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}",
|
||||
"[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
|
||||
sp.Name, Name, sp.LifecycleState);
|
||||
|
||||
return false;
|
||||
@@ -5741,7 +5803,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
if (!AuthorizeUser(aCircuit, false, out reason))
|
||||
{
|
||||
// m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
|
||||
//m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,39 +561,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
protected internal ScenePresence CreateAndAddChildScenePresence(
|
||||
IClientAPI client, AvatarAppearance appearance, PresenceType type)
|
||||
{
|
||||
ScenePresence newAvatar = null;
|
||||
|
||||
// ScenePresence always defaults to child agent
|
||||
newAvatar = new ScenePresence(client, m_parentScene, appearance, type);
|
||||
|
||||
AddScenePresence(newAvatar);
|
||||
|
||||
return newAvatar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a presence to the scene
|
||||
/// </summary>
|
||||
/// <param name="presence"></param>
|
||||
protected internal void AddScenePresence(ScenePresence presence)
|
||||
{
|
||||
// Always a child when added to the scene
|
||||
bool child = presence.IsChildAgent;
|
||||
|
||||
if (child)
|
||||
{
|
||||
m_numChildAgents++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_numRootAgents++;
|
||||
presence.AddToPhysicalScene(false);
|
||||
}
|
||||
ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
|
||||
|
||||
Entities[presence.UUID] = presence;
|
||||
|
||||
lock (m_presenceLock)
|
||||
{
|
||||
m_numChildAgents++;
|
||||
|
||||
Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
|
||||
List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
|
||||
|
||||
@@ -604,7 +580,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember the old presene reference from the dictionary
|
||||
// Remember the old presence reference from the dictionary
|
||||
ScenePresence oldref = newmap[presence.UUID];
|
||||
// Replace the presence reference in the dictionary with the new value
|
||||
newmap[presence.UUID] = presence;
|
||||
@@ -616,6 +592,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
m_scenePresenceMap = newmap;
|
||||
m_scenePresenceArray = newlist;
|
||||
}
|
||||
|
||||
return presence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2464,12 +2464,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
|
||||
|
||||
if (startedColliders.Contains(0))
|
||||
{
|
||||
if (m_lastColliders.Contains(0))
|
||||
SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
|
||||
else
|
||||
SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
|
||||
}
|
||||
SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
|
||||
if (m_lastColliders.Contains(0))
|
||||
SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
|
||||
if (endedColliders.Contains(0))
|
||||
SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
|
||||
}
|
||||
@@ -2505,6 +2502,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();
|
||||
}
|
||||
|
||||
|
||||
@@ -3243,11 +3243,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreInCurrentScene()
|
||||
{
|
||||
AddToPhysicalScene(false); // not exactly false
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// This is a state machine.
|
||||
///
|
||||
/// [Entry] => Running
|
||||
/// Running => Removing
|
||||
/// Running => PreRemove, Removing
|
||||
/// PreRemove => Running, Removing
|
||||
/// Removing => Removed
|
||||
///
|
||||
/// All other methods should only see the scene presence in running state - this is the normal operational state
|
||||
@@ -46,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public enum ScenePresenceState
|
||||
{
|
||||
Running, // Normal operation state. The scene presence is available.
|
||||
PreRemove, // The presence is due to be removed but can still be returning to running.
|
||||
Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
|
||||
Removed, // The presence has been removed from the scene and is effectively dead.
|
||||
// There is no exit from this state.
|
||||
@@ -80,8 +82,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running)
|
||||
if (newState == m_state)
|
||||
return;
|
||||
else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
|
||||
transitionOkay = true;
|
||||
else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
|
||||
transitionOkay = true;
|
||||
else if (newState == ScenePresenceState.Removing)
|
||||
{
|
||||
if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
|
||||
transitionOkay = true;
|
||||
}
|
||||
else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
|
||||
transitionOkay = true;
|
||||
}
|
||||
|
||||
@@ -624,9 +624,16 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
|
||||
int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
|
||||
avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
|
||||
|
||||
string childAgentStatus;
|
||||
|
||||
if (llClient.SceneAgent != null)
|
||||
childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
|
||||
else
|
||||
childAgentStatus = "Off!";
|
||||
|
||||
m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
|
||||
scene.RegionInfo.RegionName, llClient.Name,
|
||||
llClient.SceneAgent.IsChildAgent ? "N" : "Y",
|
||||
childAgentStatus,
|
||||
(DateTime.Now - cinfo.StartedTime).Minutes,
|
||||
avg_reqs,
|
||||
string.Format(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
54
OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
Executable file
54
OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
Executable 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
55
OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
Executable file
55
OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
Executable 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
103
OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
Executable file
103
OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
Executable 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -132,10 +216,16 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
{
|
||||
// Queue to happen after all the other taint processing
|
||||
m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
|
||||
{
|
||||
if (HasAnyChildren)
|
||||
{
|
||||
if (HasAnyChildren)
|
||||
RecomputeLinksetConstraints();
|
||||
});
|
||||
// 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,13 +444,22 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
|
||||
childPrim.LocalID, childPrim.PhysBody.AddrString);
|
||||
|
||||
// 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))
|
||||
// If asked to unlink root from root, just remove all the constraints
|
||||
if (rootPrim == childPrim || childPrim == LinksetRoot)
|
||||
{
|
||||
// Make the child refresh its location
|
||||
m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
|
||||
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))
|
||||
{
|
||||
// Make the child refresh its location
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,9 +570,9 @@ 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>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
|
||||
@@ -683,21 +683,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 +826,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);
|
||||
});
|
||||
|
||||
@@ -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,8 +300,19 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
// Called in taint-time!!
|
||||
public void ActivateIfPhysical(bool forceIt)
|
||||
{
|
||||
if (IsPhysical && PhysBody.HasPhysicalBody)
|
||||
PhysScene.PE.Activate(PhysBody, forceIt);
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
lock (_taintLock)
|
||||
{
|
||||
_taintOperations.Add(new TaintCallbackEntry(ident, callback));
|
||||
}
|
||||
|
||||
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();
|
||||
pCallback();
|
||||
else
|
||||
TaintedObject(ident, callback);
|
||||
{
|
||||
lock (_taintLock)
|
||||
{
|
||||
_taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
|
||||
@@ -8190,12 +8190,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
while (true)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}",
|
||||
// rules.Length, entity != null ? entity.Name : "NULL");
|
||||
|
||||
if (entity == null)
|
||||
return result;
|
||||
|
||||
if (entity is SceneObjectPart)
|
||||
remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
|
||||
else
|
||||
remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
|
||||
|
||||
if (remaining == null || remaining.Length <= 2)
|
||||
if (remaining == null || remaining.Length < 2)
|
||||
return result;
|
||||
|
||||
int linknumber = remaining.GetLSLIntegerItem(0);
|
||||
@@ -8400,7 +8407,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
while (idx < rules.Length)
|
||||
{
|
||||
int code = (int)rules.GetLSLIntegerItem(idx++);
|
||||
int remain = rules.Length-idx;
|
||||
int remain = rules.Length - idx;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
@@ -8483,7 +8490,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;
|
||||
|
||||
@@ -8777,7 +8784,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);
|
||||
|
||||
399
OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
Normal file
399
OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -106,6 +106,9 @@ namespace OpenSim.Server.Handlers.Grid
|
||||
case "get_default_regions":
|
||||
return GetDefaultRegions(request);
|
||||
|
||||
case "get_default_hypergrid_regions":
|
||||
return GetDefaultHypergridRegions(request);
|
||||
|
||||
case "get_fallback_regions":
|
||||
return GetFallbackRegions(request);
|
||||
|
||||
@@ -444,6 +447,36 @@ namespace OpenSim.Server.Handlers.Grid
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
|
||||
byte[] GetDefaultHypergridRegions(Dictionary<string, object> request)
|
||||
{
|
||||
//m_log.DebugFormat("[GRID HANDLER]: GetDefaultRegions");
|
||||
UUID scopeID = UUID.Zero;
|
||||
if (request.ContainsKey("SCOPEID"))
|
||||
UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
|
||||
else
|
||||
m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region range");
|
||||
|
||||
List<GridRegion> rinfos = m_GridService.GetDefaultHypergridRegions(scopeID);
|
||||
|
||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||
if ((rinfos == null) || ((rinfos != null) && (rinfos.Count == 0)))
|
||||
result["result"] = "null";
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
foreach (GridRegion rinfo in rinfos)
|
||||
{
|
||||
Dictionary<string, object> rinfoDict = rinfo.ToKeyValuePairs();
|
||||
result["region" + i] = rinfoDict;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||
|
||||
//m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
|
||||
byte[] GetFallbackRegions(Dictionary<string, object> request)
|
||||
{
|
||||
//m_log.DebugFormat("[GRID HANDLER]: GetRegionRange");
|
||||
|
||||
@@ -515,6 +515,57 @@ namespace OpenSim.Services.Connectors
|
||||
return rinfos;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||
|
||||
sendData["SCOPEID"] = scopeID.ToString();
|
||||
|
||||
sendData["METHOD"] = "get_default_hypergrid_regions";
|
||||
|
||||
List<GridRegion> rinfos = new List<GridRegion>();
|
||||
string reply = string.Empty;
|
||||
string uri = m_ServerURI + "/grid";
|
||||
try
|
||||
{
|
||||
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||
uri,
|
||||
ServerUtils.BuildQueryString(sendData));
|
||||
|
||||
//m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
|
||||
return rinfos;
|
||||
}
|
||||
|
||||
if (reply != string.Empty)
|
||||
{
|
||||
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
||||
|
||||
if (replyData != null)
|
||||
{
|
||||
Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
|
||||
foreach (object r in rinfosList)
|
||||
{
|
||||
if (r is Dictionary<string, object>)
|
||||
{
|
||||
GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
|
||||
rinfos.Add(rinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions {0} received null response",
|
||||
scopeID);
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions received null reply");
|
||||
|
||||
return rinfos;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||
|
||||
@@ -330,6 +330,12 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||
return new List<GridRegion>(0);
|
||||
}
|
||||
|
||||
public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
// TODO: Allow specifying the default grid location
|
||||
return GetDefaultRegions(scopeID);
|
||||
}
|
||||
|
||||
public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace OpenSim.Services.GridService
|
||||
{
|
||||
MainConsole.Instance.Commands.AddCommand("Regions", true,
|
||||
"deregister region id",
|
||||
"deregister region id <Region UUID>",
|
||||
"deregister region id <region-id>+",
|
||||
"Deregister a region manually.",
|
||||
String.Empty,
|
||||
HandleDeregisterRegion);
|
||||
@@ -265,8 +265,9 @@ namespace OpenSim.Services.GridService
|
||||
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY);
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY,
|
||||
(OpenSim.Framework.RegionFlags)flags);
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
@@ -478,6 +479,33 @@ namespace OpenSim.Services.GridService
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
List<GridRegion> ret = new List<GridRegion>();
|
||||
|
||||
List<RegionData> regions = m_Database.GetDefaultHypergridRegions(scopeID);
|
||||
|
||||
foreach (RegionData r in regions)
|
||||
{
|
||||
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
|
||||
ret.Add(RegionData2RegionInfo(r));
|
||||
}
|
||||
|
||||
int hgDefaultRegionsFoundOnline = regions.Count;
|
||||
|
||||
// For now, hypergrid default regions will always be given precedence but we will also return simple default
|
||||
// regions in case no specific hypergrid regions are specified.
|
||||
ret.AddRange(GetDefaultRegions(scopeID));
|
||||
|
||||
int normalDefaultRegionsFoundOnline = ret.Count - hgDefaultRegionsFoundOnline;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[GRID SERVICE]: GetDefaultHypergridRegions returning {0} hypergrid default and {1} normal default regions",
|
||||
hgDefaultRegionsFoundOnline, normalDefaultRegionsFoundOnline);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<GridRegion> ret = new List<GridRegion>();
|
||||
@@ -526,40 +554,41 @@ namespace OpenSim.Services.GridService
|
||||
|
||||
private void HandleDeregisterRegion(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length != 4)
|
||||
if (cmd.Length < 4)
|
||||
{
|
||||
MainConsole.Instance.Output("Syntax: degregister region id <Region UUID>");
|
||||
MainConsole.Instance.Output("Usage: degregister region id <region-id>+");
|
||||
return;
|
||||
}
|
||||
|
||||
string rawRegionUuid = cmd[3];
|
||||
UUID regionUuid;
|
||||
|
||||
if (!UUID.TryParse(rawRegionUuid, out regionUuid))
|
||||
for (int i = 3; i < cmd.Length; i++)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
|
||||
return;
|
||||
}
|
||||
string rawRegionUuid = cmd[i];
|
||||
UUID regionUuid;
|
||||
|
||||
GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
|
||||
if (!UUID.TryParse(rawRegionUuid, out regionUuid))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
|
||||
return;
|
||||
}
|
||||
GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
|
||||
|
||||
if (DeregisterRegion(regionUuid))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// I don't think this can ever occur if we know that the region exists.
|
||||
MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
|
||||
}
|
||||
if (region == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
if (DeregisterRegion(regionUuid))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// I don't think this can ever occur if we know that the region exists.
|
||||
MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleShowRegions(string module, string[] cmd)
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace OpenSim.Services.GridService
|
||||
{
|
||||
if (m_DefaultRegion == null)
|
||||
{
|
||||
List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
|
||||
List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
|
||||
if (defs != null && defs.Count > 0)
|
||||
m_DefaultRegion = defs[0];
|
||||
else
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace OpenSim.Services.HypergridService
|
||||
m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName);
|
||||
if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty)
|
||||
{
|
||||
List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
|
||||
List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
|
||||
if (defs != null && defs.Count > 0)
|
||||
{
|
||||
region = defs[0];
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace OpenSim.Services.Interfaces
|
||||
List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax);
|
||||
|
||||
List<GridRegion> GetDefaultRegions(UUID scopeID);
|
||||
List<GridRegion> GetDefaultHypergridRegions(UUID scopeID);
|
||||
List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
|
||||
List<GridRegion> GetHyperlinks(UUID scopeID);
|
||||
|
||||
|
||||
@@ -47,6 +47,44 @@ namespace OpenSim.Services.UserAccountService
|
||||
public GridUserService(IConfigSource config) : base(config)
|
||||
{
|
||||
m_log.Debug("[GRID USER SERVICE]: Starting user grid service");
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Users", false,
|
||||
"show grid users online",
|
||||
"show grid users online",
|
||||
"Show number of grid users registered as online.",
|
||||
"This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n."
|
||||
+ "For this reason, users online for more than 5 days are not currently counted",
|
||||
HandleShowGridUsersOnline);
|
||||
}
|
||||
|
||||
protected void HandleShowGridUsersOnline(string module, string[] cmdparams)
|
||||
{
|
||||
// if (cmdparams.Length != 4)
|
||||
// {
|
||||
// MainConsole.Instance.Output("Usage: show grid users online");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// int onlineCount;
|
||||
int onlineRecentlyCount = 0;
|
||||
|
||||
DateTime now = DateTime.UtcNow;
|
||||
|
||||
foreach (GridUserData gu in m_Database.GetAll(""))
|
||||
{
|
||||
if (bool.Parse(gu.Data["Online"]))
|
||||
{
|
||||
// onlineCount++;
|
||||
|
||||
int unixLoginTime = int.Parse(gu.Data["Login"]);
|
||||
|
||||
if ((now - Util.ToDateTime(unixLoginTime)).Days < 5)
|
||||
onlineRecentlyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.OutputFormat("Users online: {0}", onlineRecentlyCount);
|
||||
}
|
||||
|
||||
public virtual GridUserInfo GetGridUserInfo(string userID)
|
||||
|
||||
@@ -35,6 +35,11 @@ namespace pCampBot
|
||||
{
|
||||
public class AbstractBehaviour : IBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Abbreviated name of this behaviour.
|
||||
/// </summary>
|
||||
public string AbbreviatedName { get; protected set; }
|
||||
|
||||
public string Name { get; protected set; }
|
||||
|
||||
public Bot Bot { get; protected set; }
|
||||
@@ -45,5 +50,7 @@ namespace pCampBot
|
||||
{
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
public virtual void Close() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,11 @@ namespace pCampBot
|
||||
|
||||
public const int m_regionCrossingTimeout = 1000 * 60;
|
||||
|
||||
public CrossBehaviour() { Name = "Cross"; }
|
||||
public CrossBehaviour()
|
||||
{
|
||||
AbbreviatedName = "c";
|
||||
Name = "Cross";
|
||||
}
|
||||
|
||||
public override void Action()
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ using OpenMetaverse;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using pCampBot.Interfaces;
|
||||
|
||||
namespace pCampBot
|
||||
@@ -41,7 +42,11 @@ namespace pCampBot
|
||||
/// </remarks>
|
||||
public class GrabbingBehaviour : AbstractBehaviour
|
||||
{
|
||||
public GrabbingBehaviour() { Name = "Grabbing"; }
|
||||
public GrabbingBehaviour()
|
||||
{
|
||||
AbbreviatedName = "g";
|
||||
Name = "Grabbing";
|
||||
}
|
||||
|
||||
public override void Action()
|
||||
{
|
||||
@@ -56,6 +61,8 @@ namespace pCampBot
|
||||
Bot.Client.Self.Grab(prim.LocalID);
|
||||
Bot.Client.Self.GrabUpdate(prim.ID, Vector3.Zero);
|
||||
Bot.Client.Self.DeGrab(prim.LocalID);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,10 @@ namespace pCampBot
|
||||
/// </summary>
|
||||
public class NoneBehaviour : AbstractBehaviour
|
||||
{
|
||||
public NoneBehaviour() { Name = "None"; }
|
||||
public NoneBehaviour()
|
||||
{
|
||||
AbbreviatedName = "n";
|
||||
Name = "None";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ namespace pCampBot
|
||||
|
||||
public PhysicsBehaviour()
|
||||
{
|
||||
AbbreviatedName = "p";
|
||||
Name = "Physics";
|
||||
talkarray = readexcuses();
|
||||
}
|
||||
@@ -77,6 +78,12 @@ namespace pCampBot
|
||||
Bot.Client.Self.Chat(randomf, 0, ChatType.Normal);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (Bot.ConnectionState == ConnectionState.Connected)
|
||||
Bot.Client.Self.Jump(false);
|
||||
}
|
||||
|
||||
private string[] readexcuses()
|
||||
{
|
||||
string allexcuses = "";
|
||||
|
||||
@@ -29,6 +29,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using pCampBot.Interfaces;
|
||||
@@ -42,7 +43,11 @@ namespace pCampBot
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public TeleportBehaviour() { Name = "Teleport"; }
|
||||
public TeleportBehaviour()
|
||||
{
|
||||
AbbreviatedName = "t";
|
||||
Name = "Teleport";
|
||||
}
|
||||
|
||||
public override void Action()
|
||||
{
|
||||
@@ -70,6 +75,8 @@ namespace pCampBot
|
||||
Bot.Name, sourceRegion.Name, Bot.Client.Self.SimPosition, destRegion.Name, destPosition);
|
||||
|
||||
Bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition);
|
||||
|
||||
Thread.Sleep(Bot.Random.Next(3000, 10000));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,9 +72,10 @@ namespace pCampBot
|
||||
/// Behaviours implemented by this bot.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lock this list before manipulating it.
|
||||
/// Indexed by abbreviated name. There can only be one instance of a particular behaviour.
|
||||
/// Lock this structure before manipulating it.
|
||||
/// </remarks>
|
||||
public List<IBehaviour> Behaviours { get; private set; }
|
||||
public Dictionary<string, IBehaviour> Behaviours { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Objects that the bot has discovered.
|
||||
@@ -165,8 +166,6 @@ namespace pCampBot
|
||||
{
|
||||
ConnectionState = ConnectionState.Disconnected;
|
||||
|
||||
behaviours.ForEach(b => b.Initialize(this));
|
||||
|
||||
Random = new Random(Environment.TickCount);// We do stuff randomly here
|
||||
FirstName = firstName;
|
||||
LastName = lastName;
|
||||
@@ -176,12 +175,53 @@ namespace pCampBot
|
||||
StartLocation = startLocation;
|
||||
|
||||
Manager = bm;
|
||||
Behaviours = behaviours;
|
||||
|
||||
Behaviours = new Dictionary<string, IBehaviour>();
|
||||
foreach (IBehaviour behaviour in behaviours)
|
||||
AddBehaviour(behaviour);
|
||||
|
||||
// Only calling for use as a template.
|
||||
CreateLibOmvClient();
|
||||
}
|
||||
|
||||
public bool TryGetBehaviour(string abbreviatedName, out IBehaviour behaviour)
|
||||
{
|
||||
lock (Behaviours)
|
||||
return Behaviours.TryGetValue(abbreviatedName, out behaviour);
|
||||
}
|
||||
|
||||
public bool AddBehaviour(IBehaviour behaviour)
|
||||
{
|
||||
lock (Behaviours)
|
||||
{
|
||||
if (!Behaviours.ContainsKey(behaviour.AbbreviatedName))
|
||||
{
|
||||
behaviour.Initialize(this);
|
||||
Behaviours.Add(behaviour.AbbreviatedName, behaviour);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool RemoveBehaviour(string abbreviatedName)
|
||||
{
|
||||
lock (Behaviours)
|
||||
{
|
||||
IBehaviour behaviour;
|
||||
|
||||
if (!Behaviours.TryGetValue(abbreviatedName, out behaviour))
|
||||
return false;
|
||||
|
||||
behaviour.Close();
|
||||
Behaviours.Remove(abbreviatedName);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLibOmvClient()
|
||||
{
|
||||
GridClient newClient = new GridClient();
|
||||
@@ -237,16 +277,25 @@ namespace pCampBot
|
||||
private void Action()
|
||||
{
|
||||
while (ConnectionState != ConnectionState.Disconnecting)
|
||||
{
|
||||
lock (Behaviours)
|
||||
Behaviours.ForEach(
|
||||
b =>
|
||||
{
|
||||
Thread.Sleep(Random.Next(3000, 10000));
|
||||
|
||||
// m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
|
||||
b.Action();
|
||||
}
|
||||
);
|
||||
{
|
||||
foreach (IBehaviour behaviour in Behaviours.Values)
|
||||
{
|
||||
// Thread.Sleep(Random.Next(3000, 10000));
|
||||
|
||||
// m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
|
||||
behaviour.Action();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This is a really shitty way of yielding so that behaviours can be added/removed
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
lock (Behaviours)
|
||||
foreach (IBehaviour b in Behaviours.Values)
|
||||
b.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace pCampBot
|
||||
/// <summary>
|
||||
/// Behaviour switches for bots.
|
||||
/// </summary>
|
||||
private HashSet<string> m_behaviourSwitches = new HashSet<string>();
|
||||
private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
|
||||
@@ -194,6 +194,20 @@ namespace pCampBot
|
||||
+ "If no <n> is given, then all currently connected bots are disconnected.",
|
||||
HandleDisconnect);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"bot", false, "add behaviour", "add behaviour <abbreviated-name> [<bot-number>]",
|
||||
"Add a behaviour to a bot",
|
||||
"If no bot number is specified then behaviour is added to all bots.\n"
|
||||
+ "Can be performed on connected or disconnected bots.",
|
||||
HandleAddBehaviour);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"bot", false, "remove behaviour", "remove behaviour <abbreviated-name> [<bot-number>]",
|
||||
"Remove a behaviour from a bot",
|
||||
"If no bot number is specified then behaviour is added to all bots.\n"
|
||||
+ "Can be performed on connected or disconnected bots.",
|
||||
HandleRemoveBehaviour);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"bot", false, "sit", "sit", "Sit all bots on the ground.",
|
||||
HandleSit);
|
||||
@@ -212,7 +226,7 @@ namespace pCampBot
|
||||
"bot", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
"bot", false, "show bot", "show bot <first-name> <last-name>",
|
||||
"bot", false, "show bot", "show bot <bot-number>",
|
||||
"Shows the detailed status and settings of a particular bot.", HandleShowBotStatus);
|
||||
|
||||
m_bots = new List<Bot>();
|
||||
@@ -235,7 +249,7 @@ namespace pCampBot
|
||||
m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
|
||||
|
||||
Array.ForEach<string>(
|
||||
startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b));
|
||||
startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b));
|
||||
|
||||
for (int i = 0; i < botcount; i++)
|
||||
{
|
||||
@@ -243,30 +257,52 @@ namespace pCampBot
|
||||
{
|
||||
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
|
||||
|
||||
// We must give each bot its own list of instantiated behaviours since they store state.
|
||||
List<IBehaviour> behaviours = new List<IBehaviour>();
|
||||
|
||||
// Hard-coded for now
|
||||
if (m_behaviourSwitches.Contains("c"))
|
||||
behaviours.Add(new CrossBehaviour());
|
||||
|
||||
if (m_behaviourSwitches.Contains("g"))
|
||||
behaviours.Add(new GrabbingBehaviour());
|
||||
|
||||
if (m_behaviourSwitches.Contains("n"))
|
||||
behaviours.Add(new NoneBehaviour());
|
||||
|
||||
if (m_behaviourSwitches.Contains("p"))
|
||||
behaviours.Add(new PhysicsBehaviour());
|
||||
|
||||
if (m_behaviourSwitches.Contains("t"))
|
||||
behaviours.Add(new TeleportBehaviour());
|
||||
|
||||
CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
|
||||
CreateBot(
|
||||
this,
|
||||
CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
|
||||
m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<IBehaviour> CreateBehavioursFromAbbreviatedNames(HashSet<string> abbreviatedNames)
|
||||
{
|
||||
// We must give each bot its own list of instantiated behaviours since they store state.
|
||||
List<IBehaviour> behaviours = new List<IBehaviour>();
|
||||
|
||||
// Hard-coded for now
|
||||
foreach (string abName in abbreviatedNames)
|
||||
{
|
||||
IBehaviour newBehaviour = null;
|
||||
|
||||
if (abName == "c")
|
||||
newBehaviour = new CrossBehaviour();
|
||||
|
||||
if (abName == "g")
|
||||
newBehaviour = new GrabbingBehaviour();
|
||||
|
||||
if (abName == "n")
|
||||
newBehaviour = new NoneBehaviour();
|
||||
|
||||
if (abName == "p")
|
||||
newBehaviour = new PhysicsBehaviour();
|
||||
|
||||
if (abName == "t")
|
||||
newBehaviour = new TeleportBehaviour();
|
||||
|
||||
if (newBehaviour != null)
|
||||
{
|
||||
behaviours.Add(newBehaviour);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName);
|
||||
}
|
||||
}
|
||||
|
||||
return behaviours;
|
||||
}
|
||||
|
||||
public void ConnectBots(int botcount)
|
||||
{
|
||||
ConnectingBots = true;
|
||||
@@ -453,6 +489,118 @@ namespace pCampBot
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAddBehaviour(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length < 3 || cmd.Length > 4)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Usage: add behaviour <abbreviated-behaviour> [<bot-number>]");
|
||||
return;
|
||||
}
|
||||
|
||||
string rawBehaviours = cmd[2];
|
||||
|
||||
List<Bot> botsToEffect = new List<Bot>();
|
||||
|
||||
if (cmd.Length == 3)
|
||||
{
|
||||
lock (m_bots)
|
||||
botsToEffect.AddRange(m_bots);
|
||||
}
|
||||
else
|
||||
{
|
||||
int botNumber;
|
||||
if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
|
||||
return;
|
||||
|
||||
Bot bot = GetBotFromNumber(botNumber);
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
botsToEffect.Add(bot);
|
||||
}
|
||||
|
||||
|
||||
HashSet<string> rawAbbreviatedSwitchesToAdd = new HashSet<string>();
|
||||
Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b));
|
||||
|
||||
foreach (Bot bot in botsToEffect)
|
||||
{
|
||||
List<IBehaviour> behavioursAdded = new List<IBehaviour>();
|
||||
|
||||
foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd))
|
||||
{
|
||||
if (bot.AddBehaviour(behaviour))
|
||||
behavioursAdded.Add(behaviour);
|
||||
}
|
||||
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"Added behaviours {0} to bot {1}",
|
||||
string.Join(", ", behavioursAdded.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRemoveBehaviour(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length < 3 || cmd.Length > 4)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Usage: remove behaviour <abbreviated-behaviour> [<bot-number>]");
|
||||
return;
|
||||
}
|
||||
|
||||
string rawBehaviours = cmd[2];
|
||||
|
||||
List<Bot> botsToEffect = new List<Bot>();
|
||||
|
||||
if (cmd.Length == 3)
|
||||
{
|
||||
lock (m_bots)
|
||||
botsToEffect.AddRange(m_bots);
|
||||
}
|
||||
else
|
||||
{
|
||||
int botNumber;
|
||||
if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
|
||||
return;
|
||||
|
||||
Bot bot = GetBotFromNumber(botNumber);
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
botsToEffect.Add(bot);
|
||||
}
|
||||
|
||||
HashSet<string> abbreviatedBehavioursToRemove = new HashSet<string>();
|
||||
Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => abbreviatedBehavioursToRemove.Add(b));
|
||||
|
||||
foreach (Bot bot in botsToEffect)
|
||||
{
|
||||
List<IBehaviour> behavioursRemoved = new List<IBehaviour>();
|
||||
|
||||
foreach (string b in abbreviatedBehavioursToRemove)
|
||||
{
|
||||
IBehaviour behaviour;
|
||||
|
||||
if (bot.TryGetBehaviour(b, out behaviour))
|
||||
{
|
||||
bot.RemoveBehaviour(b);
|
||||
behavioursRemoved.Add(behaviour);
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"Removed behaviours {0} to bot {1}",
|
||||
string.Join(", ", behavioursRemoved.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDisconnect(string module, string[] cmd)
|
||||
{
|
||||
lock (m_bots)
|
||||
@@ -572,10 +720,11 @@ namespace pCampBot
|
||||
private void HandleShowBotsStatus(string module, string[] cmd)
|
||||
{
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Name", 30);
|
||||
cdt.AddColumn("Region", 30);
|
||||
cdt.AddColumn("Status", 14);
|
||||
cdt.AddColumn("Connections", 11);
|
||||
cdt.AddColumn("Name", 24);
|
||||
cdt.AddColumn("Region", 24);
|
||||
cdt.AddColumn("Status", 13);
|
||||
cdt.AddColumn("Conns", 5);
|
||||
cdt.AddColumn("Behaviours", 20);
|
||||
|
||||
Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>();
|
||||
foreach (object o in Enum.GetValues(typeof(ConnectionState)))
|
||||
@@ -583,13 +732,17 @@ namespace pCampBot
|
||||
|
||||
lock (m_bots)
|
||||
{
|
||||
foreach (Bot pb in m_bots)
|
||||
foreach (Bot bot in m_bots)
|
||||
{
|
||||
Simulator currentSim = pb.Client.Network.CurrentSim;
|
||||
totals[pb.ConnectionState]++;
|
||||
Simulator currentSim = bot.Client.Network.CurrentSim;
|
||||
totals[bot.ConnectionState]++;
|
||||
|
||||
cdt.AddRow(
|
||||
pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState, pb.SimulatorsCount);
|
||||
bot.Name,
|
||||
currentSim != null ? currentSim.Name : "(none)",
|
||||
bot.ConnectionState,
|
||||
bot.SimulatorsCount,
|
||||
string.Join(",", bot.Behaviours.Keys.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,22 +758,22 @@ namespace pCampBot
|
||||
|
||||
private void HandleShowBotStatus(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length != 4)
|
||||
if (cmd.Length != 3)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: show bot <first-name> <last-name>");
|
||||
MainConsole.Instance.Output("Usage: show bot <n>");
|
||||
return;
|
||||
}
|
||||
|
||||
string name = string.Format("{0} {1}", cmd[2], cmd[3]);
|
||||
int botNumber;
|
||||
|
||||
Bot bot;
|
||||
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
|
||||
return;
|
||||
|
||||
lock (m_bots)
|
||||
bot = m_bots.Find(b => b.Name == name);
|
||||
Bot bot = GetBotFromNumber(botNumber);
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
MainConsole.Instance.Output("No bot found with name {0}", name);
|
||||
MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -640,12 +793,39 @@ namespace pCampBot
|
||||
MainConsole.Instance.Output("Settings");
|
||||
|
||||
ConsoleDisplayList statusCdl = new ConsoleDisplayList();
|
||||
|
||||
statusCdl.AddRow(
|
||||
"Behaviours",
|
||||
string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll<string>(b => b.Name).ToArray()));
|
||||
|
||||
GridClient botClient = bot.Client;
|
||||
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
|
||||
|
||||
MainConsole.Instance.Output(statusCdl.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a specific bot from its number.
|
||||
/// </summary>
|
||||
/// <returns>null if no bot was found</returns>
|
||||
/// <param name='botNumber'></param>
|
||||
private Bot GetBotFromNumber(int botNumber)
|
||||
{
|
||||
string name = GenerateBotNameFromNumber(botNumber);
|
||||
|
||||
Bot bot;
|
||||
|
||||
lock (m_bots)
|
||||
bot = m_bots.Find(b => b.Name == name);
|
||||
|
||||
return bot;
|
||||
}
|
||||
|
||||
private string GenerateBotNameFromNumber(int botNumber)
|
||||
{
|
||||
return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
|
||||
}
|
||||
|
||||
internal void Grid_GridRegion(object o, GridRegionEventArgs args)
|
||||
{
|
||||
lock (RegionsKnown)
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace pCampBot.Interfaces
|
||||
{
|
||||
public interface IBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Abbreviated name of this behaviour.
|
||||
/// </summary>
|
||||
string AbbreviatedName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of this behaviour.
|
||||
/// </summary>
|
||||
@@ -45,6 +50,14 @@ namespace pCampBot.Interfaces
|
||||
/// <param name="bot"></param>
|
||||
void Initialize(Bot bot);
|
||||
|
||||
/// <summary>
|
||||
/// Close down this behaviour.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is triggered if a behaviour is removed via explicit command and when a bot is disconnected
|
||||
/// </remarks>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// Action to take when this behaviour is invoked.
|
||||
/// </summary>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace pCampBot
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public const string ConfigFileName = "pCampbot.ini";
|
||||
public const string ConfigFileName = "pCampBot.ini";
|
||||
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
|
||||
@@ -86,8 +86,8 @@
|
||||
;; from the selected region_info_source.
|
||||
allow_regionless = false
|
||||
|
||||
;; Allow child agents to see into the region even if their root counterpart isn't allowed in here
|
||||
see_into_region = true
|
||||
;; Allow child agents to see into the region even if their root counterpart isn't allowed in here
|
||||
see_into_region = true
|
||||
|
||||
; Maximum number of position, rotation and scale changes for each prim that the simulator will store for later undos
|
||||
; Increasing this number will increase memory usage.
|
||||
@@ -653,7 +653,8 @@
|
||||
|
||||
[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
|
||||
; This is set to 4095 by default because viewers released before September 2013 can't handle teleports that are greater than this distance
|
||||
; Setting to 0 will allow teleports of any distance
|
||||
max_distance = 4095
|
||||
|
||||
; Minimum user level required for HyperGrid teleports
|
||||
|
||||
@@ -151,7 +151,8 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
|
||||
; *
|
||||
[GridService]
|
||||
LocalServiceModule = "OpenSim.Services.GridService.dll:GridService"
|
||||
HypergridLinker = true
|
||||
|
||||
HypergridLinker = true
|
||||
|
||||
; Realm = "regions"
|
||||
; AllowDuplicateNames = "True"
|
||||
@@ -168,16 +169,31 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
|
||||
;; Next, we can specify properties of regions, including default and fallback regions
|
||||
;; The syntax is: Region_<RegionName> = "<flags>"
|
||||
;; or: Region_<RegionID> = "<flags>"
|
||||
;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut,Reservation,NoMove,Authenticate
|
||||
;; For example:
|
||||
;; where <flags> can be DefaultRegion, DefaultHGRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut, Reservation, NoMove, Authenticate
|
||||
;;
|
||||
;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
|
||||
;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
|
||||
;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
|
||||
;; an explicit region.
|
||||
;;
|
||||
;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
|
||||
;; region will be used.
|
||||
;;
|
||||
;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
|
||||
;; order specified. This only applies to local logins at this time, not Hypergrid connections.
|
||||
;;
|
||||
;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
|
||||
;;
|
||||
;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
|
||||
;;
|
||||
; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
|
||||
; (replace spaces with underscore)
|
||||
|
||||
;; Allow Hyperlinks to be created at the console
|
||||
;; Allow Hyperlinks to be created at the console
|
||||
HypergridLinker = true
|
||||
|
||||
;; If you have this set under [Hypergrid], no need to set it here, leave it commented
|
||||
; GatekeeperURI = "http://127.0.0.1:8002"
|
||||
;; If you have this set under [Hypergrid], no need to set it here, leave it commented
|
||||
; GatekeeperURI = "http://127.0.0.1:8002"
|
||||
|
||||
|
||||
; * This is the configuration for the freeswitch server in grid mode
|
||||
|
||||
@@ -132,8 +132,24 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
|
||||
;; Next, we can specify properties of regions, including default and fallback regions
|
||||
;; The syntax is: Region_<RegionName> = "<flags>"
|
||||
;; or: Region_<RegionID> = "<flags>"
|
||||
;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut,Reservation,NoMove,Authenticate
|
||||
;; For example:
|
||||
;; where <flags> can be DefaultRegion, DefaultHGRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut, Reservation, NoMove, Authenticate
|
||||
;;
|
||||
;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
|
||||
;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
|
||||
;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
|
||||
;; an explicit region.
|
||||
;;
|
||||
;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
|
||||
;; region will be used.
|
||||
;;
|
||||
;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
|
||||
;; order specified. This only applies to local logins at this time, not Hypergrid connections.
|
||||
;;
|
||||
;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
|
||||
;;
|
||||
;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
|
||||
;;
|
||||
;; Example specification:
|
||||
; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
|
||||
; (replace spaces with underscore)
|
||||
|
||||
|
||||
@@ -81,11 +81,27 @@
|
||||
;; Next, we can specify properties of regions, including default and fallback regions
|
||||
;; The syntax is: Region_<RegioName> = "<flags>"
|
||||
;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut
|
||||
;;
|
||||
;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
|
||||
;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
|
||||
;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
|
||||
;; an explicit region.
|
||||
;;
|
||||
;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
|
||||
;; region will be used.
|
||||
;;
|
||||
;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
|
||||
;; order specified. This only applies to local logins at this time, not Hypergrid connections.
|
||||
;;
|
||||
;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
|
||||
;;
|
||||
;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
|
||||
;;
|
||||
;; For example:
|
||||
Region_Welcome_Area = "DefaultRegion, FallbackRegion"
|
||||
|
||||
; === HG ONLY ===
|
||||
;; If you have this set under [Hypergrid], no need to set it here, leave it commented
|
||||
;; If you have this set under [Hypergrid], no need to set it here, leave it commented
|
||||
; GatekeeperURI="http://127.0.0.1:9000"
|
||||
|
||||
[LibraryModule]
|
||||
@@ -94,7 +110,7 @@
|
||||
|
||||
[LoginService]
|
||||
WelcomeMessage = "Welcome, Avatar!"
|
||||
;; If you have Gatekeeper set under [Hypergrid], no need to set it here, leave it commented
|
||||
;; If you have Gatekeeper set under [Hypergrid], no need to set it here, leave it commented
|
||||
; GatekeeperURI = "http://127.0.0.1:9000"
|
||||
|
||||
SRV_HomeURI = "http://127.0.0.1:9000"
|
||||
|
||||
@@ -2,4 +2,4 @@ Not all of the files in this directory are licensed under the BSD license. Some
|
||||
|
||||
These files are:
|
||||
|
||||
- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License)
|
||||
- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1795,6 +1795,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/"/>
|
||||
|
||||
Reference in New Issue
Block a user