From 88771aeed3d45e60a18aa9a810eeb37b8e5def12 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 9 Mar 2010 23:10:14 +0000 Subject: Cache UserLevel in ScenePresence on SP creation. Change IsAdministrator to use that stored value. --- .../World/Permissions/PermissionsModule.cs | 8 +++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 28 +++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 2211f3e..845c4c2 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -490,6 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_allowGridGods) { + ScenePresence sp = m_scene.GetScenePresence(user); + if (sp != null) + { + if (sp.UserLevel >= 200) + return true; + return false; + } + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); if (account != null) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4256be9..7661f1e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -146,7 +146,8 @@ namespace OpenSim.Region.Framework.Scenes private float m_sitAvatarHeight = 2.0f; - private float m_godlevel; + private int m_godLevel; + private int m_userLevel; private bool m_invulnerable = true; @@ -294,9 +295,14 @@ namespace OpenSim.Region.Framework.Scenes get { return m_invulnerable; } } - public float GodLevel + public int UserLevel { - get { return m_godlevel; } + get { return m_userLevel; } + } + + public int GodLevel + { + get { return m_godLevel; } } public ulong RegionHandle @@ -668,6 +674,10 @@ namespace OpenSim.Region.Framework.Scenes m_regionInfo = reginfo; m_localId = m_scene.AllocateLocalId(); + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); + + m_userLevel = account.UserLevel; + IGroupsModule gm = m_scene.RequestModuleInterface(); if (gm != null) m_grouptitle = gm.GetGroupTitle(m_uuid); @@ -2967,17 +2977,17 @@ namespace OpenSim.Region.Framework.Scenes if (account != null) { if (account.UserLevel > 0) - m_godlevel = account.UserLevel; + m_godLevel = account.UserLevel; else - m_godlevel = 200; + m_godLevel = 200; } } else { - m_godlevel = 0; + m_godLevel = 0; } - ControllingClient.SendAdminResponse(token, (uint)m_godlevel); + ControllingClient.SendAdminResponse(token, (uint)m_godLevel); } #region Child Agent Updates @@ -3068,7 +3078,7 @@ namespace OpenSim.Region.Framework.Scenes cAgent.ControlFlags = (uint)m_AgentControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - cAgent.GodLevel = (byte)m_godlevel; + cAgent.GodLevel = (byte)m_godLevel; else cAgent.GodLevel = (byte) 0; @@ -3157,7 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - m_godlevel = cAgent.GodLevel; + m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; uint i = 0; -- cgit v1.1 From dbb2edf1a67442b5e41da3cd8010574114bba7c2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 9 Mar 2010 17:09:44 -0800 Subject: Fixed caching of user accounts. --- .../LocalUserAccountServiceConnector.cs | 15 ++++---- .../RemoteUserAccountServiceConnector.cs | 15 ++++---- .../UserAccounts/UserAccountCache.cs | 44 +++++++++++++--------- .../UserAccounts/UserAccountServiceConnector.cs | 1 + .../UserAccountService/UserAccountService.cs | 2 + 5 files changed, 45 insertions(+), 32 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index 07fee79..ce0ca40 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -142,26 +142,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public UserAccount GetUserAccount(UUID scopeID, UUID userID) { - UserAccount account = m_Cache.Get(userID); - if (account != null) + bool inCache = false; + UserAccount account = m_Cache.Get(userID, out inCache); + if (inCache) return account; account = m_UserService.GetUserAccount(scopeID, userID); - if (account != null) - m_Cache.Cache(account); + m_Cache.Cache(userID, account); return account; } public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { - UserAccount account = m_Cache.Get(firstName + " " + lastName); - if (account != null) + bool inCache = false; + UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); + if (inCache) return account; account = m_UserService.GetUserAccount(scopeID, firstName, lastName); if (account != null) - m_Cache.Cache(account); + m_Cache.Cache(account.PrincipalID, account); return account; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index 1140692..488dbd5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -119,26 +119,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public override UserAccount GetUserAccount(UUID scopeID, UUID userID) { - UserAccount account = m_Cache.Get(userID); - if (account != null) + bool inCache = false; + UserAccount account = m_Cache.Get(userID, out inCache); + if (inCache) return account; account = base.GetUserAccount(scopeID, userID); - if (account != null) - m_Cache.Cache(account); + m_Cache.Cache(userID, account); return account; } public override UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { - UserAccount account = m_Cache.Get(firstName + " " + lastName); - if (account != null) + bool inCache = false; + UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); + if (inCache) return account; account = base.GetUserAccount(scopeID, firstName, lastName); if (account != null) - m_Cache.Cache(account); + m_Cache.Cache(account.PrincipalID, account); return account; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index e430fc7..a355661 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -36,50 +36,58 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts { public class UserAccountCache { - //private static readonly ILog m_log = - // LogManager.GetLogger( - // MethodBase.GetCurrentMethod().DeclaringType); - - private ICnmCache m_UUIDCache; - private Dictionary m_NameCache; + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + private ExpiringCache m_UUIDCache; + private ExpiringCache m_NameCache; public UserAccountCache() { // Warning: the size values are a bit fuzzy. What matters // most for this cache is the count value (128 entries). - m_UUIDCache = CnmSynchronizedCache.Synchronized(new CnmMemoryCache( - 128, 128*512, TimeSpan.FromMinutes(30.0))); - m_NameCache = new Dictionary(); // this one is unbound + m_UUIDCache = new ExpiringCache(); + m_NameCache = new ExpiringCache(); // this one is unbound } - public void Cache(UserAccount account) + public void Cache(UUID userID, UserAccount account) { - m_UUIDCache.Set(account.PrincipalID, account, 512); - m_NameCache[account.Name] = account.PrincipalID; + // Cache even null accounts + m_UUIDCache.AddOrUpdate(userID, account, DateTime.Now + TimeSpan.FromMinutes(2.0d)); + if (account != null) + m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, DateTime.Now + TimeSpan.FromMinutes(2.0d)); - //m_log.DebugFormat("[USER CACHE]: cached user {0} {1}", account.FirstName, account.LastName); + m_log.DebugFormat("[USER CACHE]: cached user {0}", userID); } - public UserAccount Get(UUID userID) + public UserAccount Get(UUID userID, out bool inCache) { UserAccount account = null; + inCache = false; if (m_UUIDCache.TryGetValue(userID, out account)) { //m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName); + inCache = true; return account; } return null; } - public UserAccount Get(string name) + public UserAccount Get(string name, out bool inCache) { - if (!m_NameCache.ContainsKey(name)) + inCache = false; + if (!m_NameCache.Contains(name)) return null; UserAccount account = null; - if (m_UUIDCache.TryGetValue(m_NameCache[name], out account)) - return account; + UUID uuid = UUID.Zero; + if (m_NameCache.TryGetValue(name, out uuid)) + if (m_UUIDCache.TryGetValue(uuid, out account)) + { + inCache = true; + return account; + } return null; } diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 8e7c92b..2f9b520 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -113,6 +113,7 @@ namespace OpenSim.Services.Connectors public virtual UserAccount GetUserAccount(UUID scopeID, UUID userID) { + m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUSerAccount {0}", userID); Dictionary sendData = new Dictionary(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 82c34e7..38caf74 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -200,7 +200,9 @@ namespace OpenSim.Services.UserAccountService } if (d.Length < 1) + { return null; + } return MakeUserAccount(d[0]); } -- cgit v1.1 From c5bb51b443267a8bab8dcd28c6674491cae2c01a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 9 Mar 2010 17:33:31 -0800 Subject: Changed a cryptic debug message and a wrong comment --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 2 +- OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index de324c0..128515d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -481,7 +481,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.DebugFormat("[FRIENDS]: {0} offered friendship to {1}", principalID, friendID); // This user wants to be friends with the other user. - // Let's add both relations to the DB, but one of them is inactive (-1) + // Let's add the relation backwards, in case the other is not online FriendsService.StoreFriend(friendID, principalID.ToString(), 0); // Now let's ask the other user to be friends with this user diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 83d3449..03da834 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -334,7 +334,7 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - m_log.Debug("[HGrid]: Exception " + e.Message); + m_log.Debug("[USER AGENT CONNECTOR]: Unable to contact remote server "); reason = "Exception: " + e.Message; return false; } -- cgit v1.1 From f58a0394edf3c0e4d46faf1f3053b940ba0a1c8c Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Wed, 10 Mar 2010 13:15:36 +0900 Subject: Formatting cleanup. Add copyright notices. --- OpenSim/Data/IGridUserData.cs | 2 +- OpenSim/Data/MSSQL/MSSQLAvatarData.cs | 2 +- OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs | 6 ++-- OpenSim/Data/MSSQL/MSSQLGridUserData.cs | 4 +-- OpenSim/Data/MSSQL/MSSQLManager.cs | 4 +-- OpenSim/Data/MSSQL/MSSQLUserAccountData.cs | 2 +- OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 2 +- OpenSim/Data/MySQL/MySQLGridUserData.cs | 2 +- OpenSim/Data/MySQL/MySQLPresenceData.cs | 2 +- OpenSim/Data/Null/NullPresenceData.cs | 16 +++++------ OpenSim/Data/SQLite/SQLiteAuthenticationData.cs | 2 +- OpenSim/Framework/MultipartForm.cs | 29 ++++++++++++++++++- OpenSim/Framework/SLUtil.cs | 33 ++++++++++++++++++++-- OpenSim/Framework/UntrustedWebRequest.cs | 33 ++++++++++++++++++++-- OpenSim/Framework/WebUtil.cs | 29 ++++++++++++++++++- .../Avatar/Attachments/AttachmentsModule.cs | 8 +++--- .../CoreModules/Avatar/Friends/FriendsModule.cs | 4 +-- .../Avatar/InstantMessage/MessageTransferModule.cs | 2 +- .../InventoryAccess/InventoryAccessModule.cs | 2 +- .../Presence/Tests/PresenceConnectorsTests.cs | 4 +-- .../CoreModules/World/Land/LandManagementModule.cs | 10 +++---- .../Region/CoreModules/World/Land/LandObject.cs | 2 +- .../Framework/Interfaces/IAttachmentsModule.cs | 6 ++-- .../Framework/Interfaces/IInventoryAccessModule.cs | 29 ++++++++++++++++++- OpenSim/Region/Framework/Scenes/EventManager.cs | 8 +++--- OpenSim/Region/Framework/Scenes/Scene.cs | 16 +++++------ .../Region/Framework/Scenes/SceneObjectGroup.cs | 6 ++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- .../Handlers/Hypergrid/UserAgentServerConnector.cs | 29 ++++++++++++++++++- .../Handlers/Inventory/XInventoryInConnector.cs | 2 +- OpenSim/Services/Base/ServiceBase.cs | 2 +- .../GridUser/GridUserServiceConnector.cs | 4 +-- .../Hypergrid/GatekeeperServiceConnector.cs | 29 ++++++++++++++++++- .../Hypergrid/UserAgentServiceConnector.cs | 29 ++++++++++++++++++- .../Connectors/Inventory/XInventoryConnector.cs | 2 +- .../Services/HypergridService/UserAgentService.cs | 29 ++++++++++++++++++- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 2 +- OpenSim/Services/LLLoginService/LLLoginService.cs | 29 ++++++++++++++++++- .../Services/UserAccountService/GridUserService.cs | 2 +- 40 files changed, 349 insertions(+), 79 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Data/IGridUserData.cs b/OpenSim/Data/IGridUserData.cs index abd2cef..bd7a435 100644 --- a/OpenSim/Data/IGridUserData.cs +++ b/OpenSim/Data/IGridUserData.cs @@ -44,7 +44,7 @@ namespace OpenSim.Data /// public interface IGridUserData { - GridUserData GetGridUserData(string userID); + GridUserData GetGridUserData(string userID); bool StoreGridUserData(GridUserData data); } } \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/MSSQLAvatarData.cs b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs index 4992183..49a6b09 100644 --- a/OpenSim/Data/MSSQL/MSSQLAvatarData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs @@ -47,7 +47,7 @@ namespace OpenSim.Data.MSSQL public MSSQLAvatarData(string connectionString, string realm) : base(connectionString, realm, "Avatar") - { + { } public bool Delete(UUID principalID, string name) diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index 506056d..904366e 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -110,7 +110,7 @@ namespace OpenSim.Data.MSSQL { List constraints = new List(); string query = string.Format(@"SELECT - COL_NAME(ic.object_id,ic.column_id) AS column_name + COL_NAME(ic.object_id,ic.column_id) AS column_name FROM sys.indexes AS i INNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id @@ -157,7 +157,7 @@ namespace OpenSim.Data.MSSQL string where = String.Join(" AND ", terms.ToArray()); string query = String.Format("SELECT * FROM {0} WHERE {1}", - m_Realm, where); + m_Realm, where); cmd.Connection = conn; cmd.CommandText = query; @@ -296,7 +296,7 @@ namespace OpenSim.Data.MSSQL query.AppendFormat("[{0}] = {1} ", names[i], values[i]); if (constraints.Count > 0) { - List terms = new List(); + List terms = new List(); for (int j = 0; j < constraints.Count; j++) { terms.Add(" [" + constraints[j].Key + "] = @" + constraints[j].Key); diff --git a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs index b4a945c..9993720 100644 --- a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs +++ b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs @@ -47,7 +47,7 @@ namespace OpenSim.Data.MSSQL public MSSQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "UserGrid") - { + { } public GridUserData GetGridUserData(string userID) @@ -58,7 +58,7 @@ namespace OpenSim.Data.MSSQL return null; return ret[0]; - } + } public bool StoreGridUserData(GridUserData data) { diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs index 4309b42..575fd21 100644 --- a/OpenSim/Data/MSSQL/MSSQLManager.cs +++ b/OpenSim/Data/MSSQL/MSSQLManager.cs @@ -46,7 +46,7 @@ namespace OpenSim.Data.MSSQL /// /// Connection string for ADO.net /// - private readonly string connectionString; + private readonly string connectionString; /// /// Initialize the manager and set the connectionstring @@ -196,7 +196,7 @@ namespace OpenSim.Data.MSSQL migration.Update(); } - } + } /// /// Returns the version of this DB provider diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs index 9f18e5e..e7c8dc5 100644 --- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs +++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs @@ -43,7 +43,7 @@ namespace OpenSim.Data.MSSQL { } //private string m_Realm; - //private List m_ColumnNames = null; + //private List m_ColumnNames = null; //private MSSQLManager m_database; //public MSSQLUserAccountData(string connectionString, string realm) diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 756b42d..1253e0b 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -197,7 +197,7 @@ namespace OpenSim.Data.MySQL public virtual T[] Get(string where) { using (MySqlCommand cmd = new MySqlCommand()) - { + { string query = String.Format("select * from {0} where {1}", m_Realm, where); diff --git a/OpenSim/Data/MySQL/MySQLGridUserData.cs b/OpenSim/Data/MySQL/MySQLGridUserData.cs index 15834d2..df29ecd 100644 --- a/OpenSim/Data/MySQL/MySQLGridUserData.cs +++ b/OpenSim/Data/MySQL/MySQLGridUserData.cs @@ -54,7 +54,7 @@ namespace OpenSim.Data.MySQL return null; return ret[0]; - } + } public bool StoreGridUserData(GridUserData data) { diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index 68a68af..143dbe3 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs @@ -134,7 +134,7 @@ namespace OpenSim.Data.MySQL List deleteSessions = new List(); int online = 0; - while(reader.Read()) + while (reader.Read()) { if (bool.Parse(reader["Online"].ToString())) online++; diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 9fc4595..b98b5c9 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -55,7 +55,7 @@ namespace OpenSim.Data.Null } public bool Store(PresenceData data) - { + { if (Instance != this) return Instance.Store(data); @@ -113,7 +113,7 @@ namespace OpenSim.Data.Null } public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) - { + { if (Instance != this) return Instance.SetHomeLocation(userID, regionID, position, lookAt); @@ -130,28 +130,28 @@ namespace OpenSim.Data.Null p.Data["HomePosition"] = position.ToString(); p.Data["HomeLookAt"] = lookAt.ToString(); foundone = true; - } + } } return foundone; } public PresenceData[] Get(string field, string data) - { + { if (Instance != this) return Instance.Get(field, data); // m_log.DebugFormat( -// "[NULL PRESENCE DATA]: Getting presence data for field {0} with parameter {1}", field, data); +// "[NULL PRESENCE DATA]: Getting presence data for field {0} with parameter {1}", field, data); List presences = new List(); if (field == "UserID") { foreach (PresenceData p in m_presenceData.Values) { - if (p.UserID == data) + if (p.UserID == data) { - presences.Add(p); + presences.Add(p); // Console.WriteLine("HOME for " + p.UserID + " is " + (p.Data.ContainsKey("HomeRegionID") ? p.Data["HomeRegionID"] : "Not found")); } } @@ -194,7 +194,7 @@ namespace OpenSim.Data.Null } public void Prune(string userID) - { + { if (Instance != this) { Instance.Prune(userID); diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs index 84ce775..2c28375 100644 --- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs @@ -120,7 +120,7 @@ namespace OpenSim.Data.SQLite } public bool Store(AuthenticationData data) - { + { if (data.Data.ContainsKey("UUID")) data.Data.Remove("UUID"); diff --git a/OpenSim/Framework/MultipartForm.cs b/OpenSim/Framework/MultipartForm.cs index 8ba6d22..90c4007 100644 --- a/OpenSim/Framework/MultipartForm.cs +++ b/OpenSim/Framework/MultipartForm.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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.Net; using System.IO; diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index 2fc5bdf..f6d6a7c 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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 log4net; @@ -219,7 +246,7 @@ namespace OpenSim.Framework /// Parse a notecard in Linden format to a string of ordinary text. /// /// - /// + /// public static string ParseNotecardToString(string rawInput) { string[] output = ParseNotecardToList(rawInput).ToArray(); @@ -237,7 +264,7 @@ namespace OpenSim.Framework /// public static List ParseNotecardToList(string rawInput) { - string[] input = rawInput.Replace("\r", "").Split('\n'); + string[] input = rawInput.Replace("\r", "").Split('\n'); int idx = 0; int level = 0; List output = new List(); diff --git a/OpenSim/Framework/UntrustedWebRequest.cs b/OpenSim/Framework/UntrustedWebRequest.cs index 1af7c41..e6411cc 100644 --- a/OpenSim/Framework/UntrustedWebRequest.cs +++ b/OpenSim/Framework/UntrustedWebRequest.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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.IO; using System.Net; @@ -118,7 +145,7 @@ namespace OpenSim.Framework /// True to allow loopback addresses to be used /// The URI to test for whether it should be allowed. /// - /// true if [is URI allowable] [the specified URI]; otherwise, false. + /// true if [is URI allowable] [the specified URI]; otherwise, false. /// private static bool IsUriAllowable(Uri uri, bool allowLoopback) { @@ -180,7 +207,7 @@ namespace OpenSim.Framework /// /// The ip address to check. /// - /// true if this is a loopback IP address; false otherwise. + /// true if this is a loopback IP address; false otherwise. /// private static bool IsIPv6Loopback(IPAddress ip) { diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index d9782ff..16e44af 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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.Collections.Specialized; using System.IO; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d458364..3b7fe88 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -36,7 +36,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Attachments -{ +{ public class AttachmentsModule : IAttachmentsModule, IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -204,7 +204,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (m_scene.AvatarFactory != null) m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); } - } + } public void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient) { @@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } DetachSingleAttachmentToInv(itemID, remoteClient); - } + } // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? @@ -252,6 +252,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } } - } + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 128515d..312db38 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -394,11 +394,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public IClientAPI LocateClientObject(UUID agentID) { Scene scene = GetClientScene(agentID); - if(scene == null) + if (scene == null) return null; ScenePresence presence = scene.GetScenePresence(agentID); - if(presence == null) + if (presence == null) return null; return presence.ControllingClient; diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index c0d3f31..ad050a1 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -108,7 +108,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (!m_Enabled) return; - lock(m_Scenes) + lock (m_Scenes) { m_Scenes.Remove(scene); } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 0fc467b..16e05b7 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -576,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) - { + { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index 292ff8e..63a28fc 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests m_LocalConnector = new LocalPresenceServicesConnector(config); // Let's stick in a test presence - m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); + m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); } /// @@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests p.Data = new Dictionary(); p.Data["Online"] = true.ToString(); m_presenceData.Add(UUID.Zero, p); - */ + */ string user1 = UUID.Zero.ToString(); UUID session1 = UUID.Zero; diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 38f371a..1279ac1 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.World.Land void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { //If we are forcing a position for them to go - if( forcedPosition != null ) + if (forcedPosition != null) { ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId); @@ -191,7 +191,7 @@ namespace OpenSim.Region.CoreModules.World.Land forcedPosition = null; } //if we are far away, teleport - else if(Vector3.Distance(clientAvatar.AbsolutePosition,forcedPosition.Value) > 3 ) + else if (Vector3.Distance(clientAvatar.AbsolutePosition,forcedPosition.Value) > 3) { Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}",forcedPosition.Value,clientAvatar.AbsolutePosition)); clientAvatar.Teleport(forcedPosition.Value); @@ -332,7 +332,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendYouAreRestrictedNotice(ScenePresence avatar) { - avatar.ControllingClient.SendAlertMessage( + avatar.ControllingClient.SendAlertMessage( "You are not allowed on this parcel because the land owner has restricted access."); } @@ -467,7 +467,7 @@ namespace OpenSim.Region.CoreModules.World.Land ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); } } - else if ( parcel.IsRestrictedFromLand(clientAvatar.UUID)) + else if (parcel.IsRestrictedFromLand(clientAvatar.UUID)) { //once we've sent the message once, keep going toward the target until we are done if (forcedPosition == null) @@ -479,7 +479,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { //when we are finally in a safe place, lets release the forced position lock - forcedPosition = null; + forcedPosition = null; } } } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 27d9fdb..e85136a 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -287,7 +287,7 @@ namespace OpenSim.Region.CoreModules.World.Land entry.Flags = AccessList.Ban; entry.Time = new DateTime(); //See if they are on the list, but make sure the owner isn't banned - if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar ) + if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) { //They are banned, so lets send them a notice about this parcel return true; diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 367ff3d..6cf2a2e 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -31,7 +31,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces -{ +{ public interface IAttachmentsModule { /// @@ -43,7 +43,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// - /// true if the object was successfully attached, false otherwise + /// true if the object was successfully attached, false otherwise bool AttachObject( IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent); @@ -54,7 +54,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// - /// + /// UUID SetAttachmentInventoryStatus( SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt); diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 2401402..8185258 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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 OpenSim.Framework; diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index f0d346f..dc9ae19 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -113,15 +113,15 @@ namespace OpenSim.Region.Framework.Scenes /// Fired when an object is touched/grabbed. /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of - /// the root part. + /// the root part. public event ObjectGrabDelegate OnObjectGrab; - public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); + public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); public event ObjectGrabDelegate OnObjectGrabbing; public event ObjectDeGrabDelegate OnObjectDeGrab; public event ScriptResetDelegate OnScriptReset; - public event OnPermissionErrorDelegate OnPermissionError; + public event OnPermissionErrorDelegate OnPermissionError; /// /// Fired when a new script is created. @@ -169,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); - public event ClientClosed OnClientClosed; + public event ClientClosed OnClientClosed; /// /// This is fired when a scene object property that a script might be interested in (such as color, scale or diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 311821a..87a753e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1976,7 +1976,7 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); - } + } /// /// Delete every object from the scene @@ -2644,7 +2644,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) { client.OnRezSingleAttachmentFromInv += RezSingleAttachment; - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; + client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; client.OnObjectAttach += m_sceneGraph.AttachObject; client.OnObjectDetach += m_sceneGraph.DetachObject; @@ -2696,7 +2696,7 @@ namespace OpenSim.Region.Framework.Scenes } protected virtual void UnsubscribeToClientEvents(IClientAPI client) - { + { } /// @@ -2797,13 +2797,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) - { + { client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; - client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; + client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; client.OnObjectAttach -= m_sceneGraph.AttachObject; client.OnObjectDetach -= m_sceneGraph.DetachObject; - if (AttachmentsModule != null) + if (AttachmentsModule != null) client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } @@ -3526,7 +3526,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (var parcel in AllParcels()) { - if( parcel.ContainsPoint((int)x,(int)y)) + if (parcel.ContainsPoint((int)x,(int)y)) { return parcel; } @@ -4965,7 +4965,7 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) { Vector3 ground = GetPositionAtGround(x, y); - if( avatar.AbsolutePosition.Z > ground.Z) + if (avatar.AbsolutePosition.Z > ground.Z) { ground.Z = avatar.AbsolutePosition.Z; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 37b4fd6..88deedf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -569,7 +569,7 @@ namespace OpenSim.Region.Framework.Scenes ApplyPhysics(m_scene.m_physicalPrim); // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled - // for the same object with very different properties. The caller must schedule the update. + // for the same object with very different properties. The caller must schedule the update. //ScheduleGroupForFullUpdate(); } @@ -2032,11 +2032,11 @@ namespace OpenSim.Region.Framework.Scenes /// Immediately send a full update for this scene object. /// public void SendGroupFullUpdate() - { + { if (IsDeleted) return; -// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); +// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); RootPart.SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4729382..8967252 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2869,7 +2869,7 @@ namespace OpenSim.Region.Framework.Scenes { SendFullUpdateToClient(remoteClient, clientFlags); } - } + } /// /// Send a full update for this part to all clients. diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 59db81e..b040ca77 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4024,7 +4024,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - if( message == string.Empty) + if (message == string.Empty) { ShoutError("Trying to use llTextBox with empty message."); } diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 79c6b2a..6b1152b 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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; using System.Collections.Generic; using System.Net; diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index f9db859..34f7dcc 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -289,7 +289,7 @@ namespace OpenSim.Server.Handlers.Asset foreach (InventoryItemBase i in icoll.Items) items[i.ID.ToString()] = EncodeItem(i); result["ITEMS"] = items; - } + } string xmlString = ServerUtils.BuildXmlResponse(result); m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); diff --git a/OpenSim/Services/Base/ServiceBase.cs b/OpenSim/Services/Base/ServiceBase.cs index 91d5c56..ef30cba 100644 --- a/OpenSim/Services/Base/ServiceBase.cs +++ b/OpenSim/Services/Base/ServiceBase.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Base // m_log.DebugFormat("[SERVICE BASE]: Found type {0}", pluginType); if (pluginType.IsPublic) - { + { if (className != String.Empty && pluginType.ToString() != pluginType.Namespace + "." + className) diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs index ce88236..0e85067 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs @@ -28,9 +28,9 @@ using System; namespace OpenSim.Services.Connectors -{ +{ public class GridUserServiceConnector - { + { public GridUserServiceConnector() { } diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 9f73b38..c426bba 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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; using System.Collections.Generic; using System.Drawing; diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 03da834..3e91e3a 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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; using System.Collections.Generic; using System.IO; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index 9821dd4..0cc1978 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -126,7 +126,7 @@ namespace OpenSim.Services.Connectors }); if (ret == null) - return null; + return null; if (ret.Count == 0) return null; diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 15379b5..26f211b 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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.Net; using System.Reflection; diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 05f5b4c..1a59213 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -623,7 +623,7 @@ namespace OpenSim.Services.LLLoginService } private InventoryData GetInventorySkeleton(List folders) - { + { UUID rootID = UUID.Zero; ArrayList AgentInventoryArray = new ArrayList(); Hashtable TempHash; diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index ae729f8..1578873 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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.Net; using System.Reflection; diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs index 36cce75..c6e33bb 100644 --- a/OpenSim/Services/UserAccountService/GridUserService.cs +++ b/OpenSim/Services/UserAccountService/GridUserService.cs @@ -58,7 +58,7 @@ namespace OpenSim.Services.UserAccountService info.HomePosition = Vector3.Parse(d.Data["HomePosition"]); info.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); - return info; + return info; } public bool StoreGridUserInfo(GridUserInfo info) -- cgit v1.1 From 04a6b1caf8033a413efce7db4cda4de4bf935a01 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 10 Mar 2010 05:31:34 +0000 Subject: Reintroduce a check that was dropped from permissions --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 845c4c2..5c7f3b7 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -618,7 +618,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return objectOwnerMask; // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set - if (IsEstateManager(user) && m_RegionOwnerIsGod) + if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) return objectOwnerMask; // Admin should be able to edit anything in the sim (including admin objects) -- cgit v1.1 From 2af97b46ecc96a58028e53045efffd75c07ec857 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Wed, 10 Mar 2010 14:05:49 -0800 Subject: * Cleaned up and commented the messy SendInventoryUpdate, fixed a broken debug line, and commented the debug line out since it can quickly become noisy --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index dad0efd..7277527 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1102,18 +1102,18 @@ namespace OpenSim.Region.Framework.Scenes if (folder == null) return; - m_log.DebugFormat("[AGENT INVENTORY]: Send Inventory Folder {0} Update to {1} {2}", folder.Name, client.FirstName, client.LastName); + // Fetch the folder contents InventoryCollection contents = InventoryService.GetFolderContent(client.AgentId, folder.ID); - InventoryFolderBase containingFolder = new InventoryFolderBase(); - containingFolder.ID = folder.ID; - containingFolder.Owner = client.AgentId; + + // Fetch the folder itself to get its current version + InventoryFolderBase containingFolder = new InventoryFolderBase(folder.ID, client.AgentId); containingFolder = InventoryService.GetFolder(containingFolder); - if (containingFolder != null) - { - int version = containingFolder.Version; - client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders, version, fetchFolders, fetchItems); - } + //m_log.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}", + // contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName); + + if (containingFolder != null) + client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders, containingFolder.Version, fetchFolders, fetchItems); } /// -- cgit v1.1 From 265c24ec33f53681e6b03684d9c453d0b1e91ce5 Mon Sep 17 00:00:00 2001 From: Mikko Pallari Date: Wed, 10 Mar 2010 14:44:53 +0200 Subject: Changed some properties and methods from private to protected in LLLoginResponse and LLLoginService so they could be inherited better. --- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 6 +++--- OpenSim/Services/LLLoginService/LLLoginService.cs | 24 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 1a59213..ee30fa3 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -47,9 +47,9 @@ namespace OpenSim.Services.LLLoginService { public class LLFailedLoginResponse : OpenSim.Services.Interfaces.FailedLoginResponse { - string m_key; - string m_value; - string m_login; + protected string m_key; + protected string m_value; + protected string m_login; public static LLFailedLoginResponse UserProblem; public static LLFailedLoginResponse AuthorizationProblem; diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 1578873..1eaf4d4 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -51,24 +51,24 @@ namespace OpenSim.Services.LLLoginService private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static bool Initialized = false; - private IUserAccountService m_UserAccountService; - private IAuthenticationService m_AuthenticationService; - private IInventoryService m_InventoryService; - private IGridService m_GridService; - private IPresenceService m_PresenceService; + protected IUserAccountService m_UserAccountService; + protected IAuthenticationService m_AuthenticationService; + protected IInventoryService m_InventoryService; + protected IGridService m_GridService; + protected IPresenceService m_PresenceService; private ISimulationService m_LocalSimulationService; private ISimulationService m_RemoteSimulationService; - private ILibraryService m_LibraryService; - private IFriendsService m_FriendsService; - private IAvatarService m_AvatarService; + protected ILibraryService m_LibraryService; + protected IFriendsService m_FriendsService; + protected IAvatarService m_AvatarService; private IUserAgentService m_UserAgentService; private GatekeeperServiceConnector m_GatekeeperConnector; private string m_DefaultRegionName; - private string m_WelcomeMessage; + protected string m_WelcomeMessage; private bool m_RequireInventory; - private int m_MinLoginLevel; + protected int m_MinLoginLevel; private string m_GatekeeperURL; IConfig m_LoginServerConfig; @@ -286,7 +286,7 @@ namespace OpenSim.Services.LLLoginService } } - private GridRegion FindDestination(UserAccount account, PresenceInfo pinfo, UUID sessionID, string startLocation, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt) + protected GridRegion FindDestination(UserAccount account, PresenceInfo pinfo, UUID sessionID, string startLocation, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt) { m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation); @@ -497,7 +497,7 @@ namespace OpenSim.Services.LLLoginService } } - private AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, + protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, UUID session, UUID secureSession, Vector3 position, string currentWhere, out string where, out string reason) { where = currentWhere; -- cgit v1.1 From 20406498711d1f26037ae32e1b7f8378b01ad848 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 11 Mar 2010 10:05:03 -0800 Subject: Adding the SimianGrid connectors --- .../SimianGrid/SimianAssetServiceConnector.cs | 407 ++++++++++ .../SimianAuthenticationServiceConnector.cs | 198 +++++ .../SimianGrid/SimianAvatarServiceConnector.cs | 259 ++++++ .../SimianGrid/SimianFriendsServiceConnector.cs | 229 ++++++ .../Services/Connectors/SimianGrid/SimianGrid.cs | 31 + .../SimianGrid/SimianGridServiceConnector.cs | 418 ++++++++++ .../SimianGrid/SimianInventoryServiceConnector.cs | 880 +++++++++++++++++++++ .../SimianGrid/SimianPresenceServiceConnector.cs | 502 ++++++++++++ .../Connectors/SimianGrid/SimianProfiles.cs | 432 ++++++++++ .../SimianUserAccountServiceConnector.cs | 307 +++++++ 10 files changed, 3663 insertions(+) create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs new file mode 100644 index 0000000..9fb7723 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -0,0 +1,407 @@ +/* + * 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.IO; +using System.Net; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects to the SimianGrid asset service + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + private static string ZeroID = UUID.Zero.ToString(); + + private string m_serverUrl = String.Empty; + private IImprovedAssetCache m_cache; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) + { + if (m_cache == null) + { + IImprovedAssetCache cache = scene.RequestModuleInterface(); + if (cache is ISharedRegionModule) + m_cache = cache; + } + } + public void PostInitialise() { } + public void Close() { } + + public SimianAssetServiceConnector() { } + public string Name { get { return "SimianAssetServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianAssetServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["AssetService"]; + if (gridConfig == null) + { + m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini"); + throw new Exception("Asset connector init error"); + } + + string serviceUrl = gridConfig.GetString("AssetServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[ASSET CONNECTOR]: No AssetServerURI in section AssetService"); + throw new Exception("Asset connector init error"); + } + + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; + + m_serverUrl = serviceUrl; + } + + #region IAssetService + + public AssetBase Get(string id) + { + AssetBase asset = null; + + // Cache fetch + if (m_cache != null) + { + asset = m_cache.Get(id); + if (asset != null) + return asset; + } + + Uri url; + + // Determine if id is an absolute URL or a grid-relative UUID + if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + url = new Uri(m_serverUrl + id); + + try + { + HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; + + // Create the asset object + asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); + + UUID assetID; + if (UUID.TryParse(id, out assetID)) + asset.FullID = assetID; + + // Grab the asset data from the response stream + using (MemoryStream stream = new MemoryStream()) + { + responseStream.CopyTo(stream, Int32.MaxValue); + asset.Data = stream.ToArray(); + } + } + } + + // Cache store + if (m_cache != null && asset != null) + m_cache.Cache(asset); + + return asset; + } + catch (Exception ex) + { + m_log.Warn("[ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); + return null; + } + } + + /// + /// Get an asset's metadata + /// + /// + /// + public AssetMetadata GetMetadata(string id) + { + AssetMetadata metadata = null; + + // Cache fetch + if (m_cache != null) + { + AssetBase asset = m_cache.Get(id); + if (asset != null) + return asset.Metadata; + } + + Uri url; + + // Determine if id is an absolute URL or a grid-relative UUID + if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + url = new Uri(m_serverUrl + id); + + try + { + HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + request.Method = "HEAD"; + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + // Create the metadata object + metadata = new AssetMetadata(); + metadata.ContentType = response.ContentType; + metadata.ID = id; + + UUID uuid; + if (UUID.TryParse(id, out uuid)) + metadata.FullID = uuid; + + string lastModifiedStr = response.Headers.Get("Last-Modified"); + if (!String.IsNullOrEmpty(lastModifiedStr)) + { + DateTime lastModified; + if (DateTime.TryParse(lastModifiedStr, out lastModified)) + metadata.CreationDate = lastModified; + } + } + } + } + catch (Exception ex) + { + m_log.Warn("[ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); + } + + return metadata; + } + + public byte[] GetData(string id) + { + AssetBase asset = Get(id); + + if (asset != null) + return asset.Data; + + return null; + } + + /// + /// Get an asset asynchronously + /// + /// The asset id + /// Represents the requester. Passed back via the handler + /// The handler to call back once the asset has been retrieved + /// True if the id was parseable, false otherwise + public bool Get(string id, Object sender, AssetRetrieved handler) + { + Util.FireAndForget( + delegate(object o) + { + AssetBase asset = Get(id); + handler(id, sender, asset); + } + ); + + return true; + } + + /// + /// Creates a new asset + /// + /// Returns a random ID if none is passed into it + /// + /// + public string Store(AssetBase asset) + { + bool storedInCache = false; + string errorMessage = null; + + // AssetID handling + if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID) + { + asset.FullID = UUID.Random(); + asset.ID = asset.FullID.ToString(); + } + + // Cache handling + if (m_cache != null) + { + m_cache.Cache(asset); + storedInCache = true; + } + + // Local asset handling + if (asset.Local) + { + if (!storedInCache) + { + m_log.Error("Cannot store local " + asset.Metadata.ContentType + " asset without an asset cache"); + asset.ID = null; + asset.FullID = UUID.Zero; + } + + return asset.ID; + } + + // Distinguish public and private assets + bool isPublic = true; + switch ((AssetType)asset.Type) + { + case AssetType.CallingCard: + case AssetType.Gesture: + case AssetType.LSLBytecode: + case AssetType.LSLText: + isPublic = false; + break; + } + + // Make sure ContentType is set + if (String.IsNullOrEmpty(asset.Metadata.ContentType)) + asset.Metadata.ContentType = SLUtil.SLAssetTypeToContentType(asset.Type); + + // Build the remote storage request + List postParameters = new List() + { + new MultipartForm.Parameter("AssetID", asset.FullID.ToString()), + new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID), + new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"), + new MultipartForm.Parameter("Public", isPublic ? "1" : "0"), + new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data) + }; + + // Make the remote storage request + try + { + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl); + + HttpWebResponse response = MultipartForm.Post(request, postParameters); + using (Stream responseStream = response.GetResponseStream()) + { + try + { + string responseStr = responseStream.GetStreamString(); + OSD responseOSD = OSDParser.Deserialize(responseStr); + if (responseOSD.Type == OSDType.Map) + { + OSDMap responseMap = (OSDMap)responseOSD; + if (responseMap["Success"].AsBoolean()) + return asset.ID; + else + errorMessage = "Upload failed: " + responseMap["Message"].AsString(); + } + else + { + errorMessage = "Response format was invalid."; + } + } + catch + { + errorMessage = "Failed to parse the response."; + } + } + } + catch (WebException ex) + { + errorMessage = ex.Message; + } + + m_log.WarnFormat("[ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}", + asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage); + return null; + } + + /// + /// Update an asset's content + /// + /// Attachments and bare scripts need this!! + /// + /// + /// + public bool UpdateContent(string id, byte[] data) + { + AssetBase asset = Get(id); + + if (asset == null) + { + m_log.Warn("[ASSET CONNECTOR]: Failed to fetch asset " + id + " for updating"); + return false; + } + + asset.Data = data; + + string result = Store(asset); + return !String.IsNullOrEmpty(result); + } + + /// + /// Delete an asset + /// + /// + /// + public bool Delete(string id) + { + if (m_cache != null) + m_cache.Expire(id); + + string url = m_serverUrl + id; + + OSDMap response = WebUtil.ServiceRequest(url, "DELETE"); + if (response["Success"].AsBoolean()) + return true; + else + m_log.Warn("[ASSET CONNECTOR]: Failed to delete asset " + id + " from the asset service"); + + return false; + } + + #endregion IAssetService + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs new file mode 100644 index 0000000..ec66341 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -0,0 +1,198 @@ +/* + * 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.Specialized; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects authentication/authorization to the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianAuthenticationServiceConnector() { } + public string Name { get { return "SimianAuthenticationServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianAuthenticationServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig assetConfig = source.Configs["AuthenticationService"]; + if (assetConfig == null) + { + m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini"); + throw new Exception("Authentication connector init error"); + } + + string serviceURI = assetConfig.GetString("AuthenticationServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService"); + throw new Exception("Authentication connector init error"); + } + + m_serverUrl = serviceURI; + } + + public string Authenticate(UUID principalID, string password, int lifetime) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetIdentities" }, + { "UserID", principalID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Identities"] is OSDArray) + { + OSDArray identities = (OSDArray)response["Identities"]; + for (int i = 0; i < identities.Count; i++) + { + OSDMap identity = identities[i] as OSDMap; + if (identity != null) + { + if (identity["Type"].AsString() == "md5hash") + { + string credential = identity["Credential"].AsString(); + + if (password == credential || Utils.MD5String(password) == credential) + return Authorize(principalID); + } + } + } + + m_log.Warn("[AUTH CONNECTOR]: Authentication failed for " + principalID); + } + else + { + m_log.Warn("[AUTH CONNECTOR]: Failed to retrieve identities for " + principalID + ": " + + response["Message"].AsString()); + } + + return String.Empty; + } + + public bool Verify(UUID principalID, string token, int lifetime) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSession" }, + { "SessionID", token } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.Warn("[AUTH CONNECTOR]: Could not verify session for " + principalID + ": " + + response["Message"].AsString()); + } + + return false; + } + + public bool Release(UUID principalID, string token) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveSession" }, + { "UserID", principalID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.Warn("[AUTH CONNECTOR]: Failed to remove session for " + principalID + ": " + + response["Message"].AsString()); + } + + return false; + } + + public bool SetPassword(UUID principalID, string passwd) + { + // TODO: Use GetIdentities to find the md5hash identity for principalID + // and then update it with AddIdentity + m_log.Error("[AUTH CONNECTOR]: Changing passwords is not implemented yet"); + return false; + } + + private string Authorize(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddSession" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + return response["SessionID"].AsUUID().ToString(); + else + return String.Empty; + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs new file mode 100644 index 0000000..220f143 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -0,0 +1,259 @@ +/* + * 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.Collections.Specialized; +using System.IO; +using System.Net; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects avatar appearance data to the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + private static string ZeroID = UUID.Zero.ToString(); + + private string m_serverUrl = String.Empty; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianAvatarServiceConnector() { } + public string Name { get { return "SimianAvatarServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianAvatarServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["AvatarService"]; + if (gridConfig == null) + { + m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini"); + throw new Exception("Avatar connector init error"); + } + + string serviceUrl = gridConfig.GetString("AvatarServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[AVATAR CONNECTOR]: No AvatarServerURI in section AvatarService"); + throw new Exception("Avatar connector init error"); + } + + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; + + m_serverUrl = serviceUrl; + } + + #region IAvatarService + + public AvatarData GetAvatar(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDMap map = null; + try { map = OSDParser.DeserializeJson(response["LLAppearance"].AsString()) as OSDMap; } + catch { } + + if (map != null) + { + AvatarWearable[] wearables = new AvatarWearable[13]; + wearables[0] = new AvatarWearable(map["ShapeItem"].AsUUID(), map["ShapeAsset"].AsUUID()); + wearables[1] = new AvatarWearable(map["SkinItem"].AsUUID(), map["SkinAsset"].AsUUID()); + wearables[2] = new AvatarWearable(map["HairItem"].AsUUID(), map["HairAsset"].AsUUID()); + wearables[3] = new AvatarWearable(map["EyesItem"].AsUUID(), map["EyesAsset"].AsUUID()); + wearables[4] = new AvatarWearable(map["ShirtItem"].AsUUID(), map["ShirtAsset"].AsUUID()); + wearables[5] = new AvatarWearable(map["PantsItem"].AsUUID(), map["PantsAsset"].AsUUID()); + wearables[6] = new AvatarWearable(map["ShoesItem"].AsUUID(), map["ShoesAsset"].AsUUID()); + wearables[7] = new AvatarWearable(map["SocksItem"].AsUUID(), map["SocksAsset"].AsUUID()); + wearables[8] = new AvatarWearable(map["JacketItem"].AsUUID(), map["JacketAsset"].AsUUID()); + wearables[9] = new AvatarWearable(map["GlovesItem"].AsUUID(), map["GlovesAsset"].AsUUID()); + wearables[10] = new AvatarWearable(map["UndershirtItem"].AsUUID(), map["UndershirtAsset"].AsUUID()); + wearables[11] = new AvatarWearable(map["UnderpantsItem"].AsUUID(), map["UnderpantsAsset"].AsUUID()); + wearables[12] = new AvatarWearable(map["SkirtItem"].AsUUID(), map["SkirtAsset"].AsUUID()); + + AvatarAppearance appearance = new AvatarAppearance(userID); + appearance.Wearables = wearables; + appearance.AvatarHeight = (float)map["Height"].AsReal(); + + AvatarData avatar = new AvatarData(appearance); + + // Get attachments + map = null; + try { map = OSDParser.DeserializeJson(response["LLAttachments"].AsString()) as OSDMap; } + catch { } + + if (map != null) + { + foreach (KeyValuePair kvp in map) + avatar.Data[kvp.Key] = kvp.Value.AsString(); + } + + return avatar; + } + else + { + m_log.Warn("[AVATAR CONNECTOR]: Failed to get user appearance for " + userID + + ", LLAppearance is missing or invalid"); + return null; + } + } + else + { + m_log.Warn("[AVATAR CONNECTOR]: Failed to get user appearance for " + userID + ": " + + response["Message"].AsString()); + } + + return null; + } + + public bool SetAvatar(UUID userID, AvatarData avatar) + { + m_log.Debug("[AVATAR CONNECTOR]: SetAvatar called for " + userID); + + if (avatar.AvatarType == 1) // LLAvatar + { + AvatarAppearance appearance = avatar.ToAvatarAppearance(userID); + + OSDMap map = new OSDMap(); + + map["Height"] = OSD.FromReal(appearance.AvatarHeight); + + map["ShapeItem"] = OSD.FromUUID(appearance.BodyItem); + map["ShapeAsset"] = OSD.FromUUID(appearance.BodyAsset); + map["SkinItem"] = OSD.FromUUID(appearance.SkinItem); + map["SkinAsset"] = OSD.FromUUID(appearance.SkinAsset); + map["HairItem"] = OSD.FromUUID(appearance.HairItem); + map["HairAsset"] = OSD.FromUUID(appearance.HairAsset); + map["EyesItem"] = OSD.FromUUID(appearance.EyesItem); + map["EyesAsset"] = OSD.FromUUID(appearance.EyesAsset); + map["ShirtItem"] = OSD.FromUUID(appearance.ShirtItem); + map["ShirtAsset"] = OSD.FromUUID(appearance.ShirtAsset); + map["PantsItem"] = OSD.FromUUID(appearance.PantsItem); + map["PantsAsset"] = OSD.FromUUID(appearance.PantsAsset); + map["ShoesItem"] = OSD.FromUUID(appearance.ShoesItem); + map["ShoesAsset"] = OSD.FromUUID(appearance.ShoesAsset); + map["SocksItem"] = OSD.FromUUID(appearance.SocksItem); + map["SocksAsset"] = OSD.FromUUID(appearance.SocksAsset); + map["JacketItem"] = OSD.FromUUID(appearance.JacketItem); + map["JacketAsset"] = OSD.FromUUID(appearance.JacketAsset); + map["GlovesItem"] = OSD.FromUUID(appearance.GlovesItem); + map["GlovesAsset"] = OSD.FromUUID(appearance.GlovesAsset); + map["UndershirtItem"] = OSD.FromUUID(appearance.UnderShirtItem); + map["UndershirtAsset"] = OSD.FromUUID(appearance.UnderShirtAsset); + map["UnderpantsItem"] = OSD.FromUUID(appearance.UnderPantsItem); + map["UnderpantsAsset"] = OSD.FromUUID(appearance.UnderPantsAsset); + map["SkirtItem"] = OSD.FromUUID(appearance.SkirtItem); + map["SkirtAsset"] = OSD.FromUUID(appearance.SkirtAsset); + + OSDMap items = new OSDMap(); + foreach (KeyValuePair kvp in avatar.Data) + { + if (kvp.Key.StartsWith("_ap_")) + items.Add(kvp.Key, OSD.FromString(kvp.Value)); + } + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "LLAppearance", OSDParser.SerializeJsonString(map) }, + { "LLAttachments", OSDParser.SerializeJsonString(items) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[AVATAR CONNECTOR]: Failed saving appearance for " + userID + ": " + response["Message"].AsString()); + + return success; + } + else + { + m_log.Error("[AVATAR CONNECTOR]: Can't save appearance for " + userID + ". Unhandled avatar type " + avatar.AvatarType); + return false; + } + } + + public bool ResetAvatar(UUID userID) + { + m_log.Error("[AVATAR CONNECTOR]: ResetAvatar called for " + userID + ", implement this"); + return false; + } + + public bool SetItems(UUID userID, string[] names, string[] values) + { + m_log.Error("[AVATAR CONNECTOR]: SetItems called for " + userID + " with " + names.Length + " names and " + values.Length + " values, implement this"); + return false; + } + + public bool RemoveItems(UUID userID, string[] names) + { + m_log.Error("[AVATAR CONNECTOR]: RemoveItems called for " + userID + " with " + names.Length + " names, implement this"); + return false; + } + + #endregion IAvatarService + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs new file mode 100644 index 0000000..3952a8c --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -0,0 +1,229 @@ +/* + * 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.Collections.Specialized; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Stores and retrieves friend lists from the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianFriendsServiceConnector : IFriendsService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianFriendsServiceConnector() { } + public string Name { get { return "SimianFriendsServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianFriendsServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig assetConfig = source.Configs["FriendsService"]; + if (assetConfig == null) + { + m_log.Error("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini"); + throw new Exception("Friends connector init error"); + } + + string serviceURI = assetConfig.GetString("FriendsServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[FRIENDS CONNECTOR]: No Server URI named in section FriendsService"); + throw new Exception("Friends connector init error"); + } + + m_serverUrl = serviceURI; + } + + #region IFriendsService + + public FriendInfo[] GetFriends(UUID principalID) + { + Dictionary friends = new Dictionary(); + + OSDArray friendsArray = GetFriended(principalID); + OSDArray friendedMeArray = GetFriendedBy(principalID); + + // Load the list of friends and their granted permissions + for (int i = 0; i < friendsArray.Count; i++) + { + OSDMap friendEntry = friendsArray[i] as OSDMap; + if (friendEntry != null) + { + UUID friendID = friendEntry["Key"].AsUUID(); + + FriendInfo friend = new FriendInfo(); + friend.PrincipalID = principalID; + friend.Friend = friendID.ToString(); + friend.MyFlags = friendEntry["Value"].AsInteger(); + friend.TheirFlags = -1; + + friends[friendID] = friend; + } + } + + // Load the permissions those friends have granted to this user + for (int i = 0; i < friendedMeArray.Count; i++) + { + OSDMap friendedMeEntry = friendedMeArray[i] as OSDMap; + if (friendedMeEntry != null) + { + UUID friendID = friendedMeEntry["OwnerID"].AsUUID(); + + FriendInfo friend; + if (friends.TryGetValue(friendID, out friend)) + friend.TheirFlags = friendedMeEntry["Value"].AsInteger(); + } + } + + // Convert the dictionary of friends to an array and return it + FriendInfo[] array = new FriendInfo[friends.Count]; + int j = 0; + foreach (FriendInfo friend in friends.Values) + array[j++] = friend; + + return array; + } + + public bool StoreFriend(UUID principalID, string friend, int flags) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddGeneric" }, + { "OwnerID", principalID.ToString() }, + { "Type", "Friend" }, + { "Key", friend }, + { "Value", flags.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Error("[FRIENDS CONNECTOR]: Failed to store friend " + friend + " for user " + principalID + ": " + response["Message"].AsString()); + + return success; + } + + public bool Delete(UUID principalID, string friend) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveGeneric" }, + { "OwnerID", principalID.ToString() }, + { "Type", "Friend" }, + { "Key", friend } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Error("[FRIENDS CONNECTOR]: Failed to remove friend " + friend + " for user " + principalID + ": " + response["Message"].AsString()); + + return success; + } + + #endregion IFriendsService + + private OSDArray GetFriended(UUID ownerID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", "Friend" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + return (OSDArray)response["Entries"]; + } + else + { + m_log.Warn("[FRIENDS CONNECTOR]: Failed to retrieve friends for user " + ownerID + ": " + response["Message"].AsString()); + return new OSDArray(0); + } + } + + private OSDArray GetFriendedBy(UUID ownerID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Key", ownerID.ToString() }, + { "Type", "Friend" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + return (OSDArray)response["Entries"]; + } + else + { + m_log.Warn("[FRIENDS CONNECTOR]: Failed to retrieve reverse friends for user " + ownerID + ": " + response["Message"].AsString()); + return new OSDArray(0); + } + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs new file mode 100644 index 0000000..41ed2f1 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs @@ -0,0 +1,31 @@ +/* + * 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 Mono.Addins; + +[assembly: Addin("SimianGrid", "1.0")] +[assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs new file mode 100644 index 0000000..16819d1 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -0,0 +1,418 @@ +/* + * 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.Collections.Specialized; +using System.Net; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects region registration and neighbor lookups to the SimianGrid + /// backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianGridServiceConnector : IGridService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianGridServiceConnector() { } + public string Name { get { return "SimianGridServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianGridServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig == null) + { + m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); + throw new Exception("Grid connector init error"); + } + + string serviceUrl = gridConfig.GetString("GridServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[GRID CONNECTOR]: No Server URI named in section GridService"); + throw new Exception("Grid connector init error"); + } + + m_serverUrl = serviceUrl; + } + + #region IGridService + + public string RegisterRegion(UUID scopeID, GridRegion regionInfo) + { + Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); + Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); + + string httpAddress = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "/"; + + OSDMap extraData = new OSDMap + { + { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, + { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) }, + { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) }, + { "ExternalAddress", OSD.FromString(regionInfo.ExternalEndPoint.Address.ToString()) }, + { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) }, + { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) }, + { "Access", OSD.FromInteger(regionInfo.Access) }, + { "RegionSecret", OSD.FromString(regionInfo.RegionSecret) }, + { "EstateOwner", OSD.FromUUID(regionInfo.EstateOwner) }, + { "Token", OSD.FromString(regionInfo.Token) } + }; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddScene" }, + { "SceneID", regionInfo.RegionID.ToString() }, + { "Name", regionInfo.RegionName }, + { "MinPosition", minPosition.ToString() }, + { "MaxPosition", maxPosition.ToString() }, + { "Address", httpAddress }, + { "Enabled", "1" }, + { "ExtraData", OSDParser.SerializeJsonString(extraData) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + return String.Empty; + else + return "Region registration for " + regionInfo.RegionName + " failed: " + response["Message"].AsString(); + } + + public bool DeregisterRegion(UUID regionID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddScene" }, + { "SceneID", regionID.ToString() }, + { "Enabled", "0" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[GRID CONNECTOR]: Region deregistration for " + regionID + " failed: " + response["Message"].AsString()); + + return success; + } + + public List GetNeighbours(UUID scopeID, UUID regionID) + { + const int NEIGHBOR_RADIUS = 128; + + GridRegion region = GetRegionByUUID(scopeID, regionID); + + if (region != null) + { + List regions = GetRegionRange(scopeID, + region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + (int)Constants.RegionSize + NEIGHBOR_RADIUS, + region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + (int)Constants.RegionSize + NEIGHBOR_RADIUS); + + for (int i = 0; i < regions.Count; i++) + { + if (regions[i].RegionID == regionID) + { + regions.RemoveAt(i); + break; + } + } + + m_log.Debug("[GRID CONNECTOR]: Found " + regions.Count + " neighbors for region " + regionID); + return regions; + } + + return new List(0); + } + + public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScene" }, + { "SceneID", regionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return ResponseToGridRegion(response); + } + else + { + m_log.Warn("[GRID CONNECTOR]: Grid service did not find a match for region " + regionID); + return null; + } + } + + public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) + { + // Go one meter in from the requested x/y coords to avoid requesting a position + // that falls on the border of two sims + Vector3d position = new Vector3d(x + 1, y + 1, 0.0); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScene" }, + { "Position", position.ToString() }, + { "Enabled", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return ResponseToGridRegion(response); + } + else + { + //m_log.InfoFormat("[GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}", + // x / Constants.RegionSize, y / Constants.RegionSize); + return null; + } + } + + public GridRegion GetRegionByName(UUID scopeID, string regionName) + { + List regions = GetRegionsByName(scopeID, regionName, 1); + + m_log.Debug("[GRID CONNECTOR]: Got " + regions.Count + " matches for region name " + regionName); + + if (regions.Count > 0) + return regions[0]; + + return null; + } + + public List GetRegionsByName(UUID scopeID, string name, int maxNumber) + { + List foundRegions = new List(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScenes" }, + { "NameQuery", name }, + { "Enabled", "1" } + }; + if (maxNumber > 0) + requestArgs["MaxNumber"] = maxNumber.ToString(); + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDArray array = response["Scenes"] as OSDArray; + if (array != null) + { + for (int i = 0; i < array.Count; i++) + { + GridRegion region = ResponseToGridRegion(array[i] as OSDMap); + if (region != null) + foundRegions.Add(region); + } + } + } + + return foundRegions; + } + + public List GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax) + { + List foundRegions = new List(); + + Vector3d minPosition = new Vector3d(xmin, ymin, 0.0); + Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScenes" }, + { "MinPosition", minPosition.ToString() }, + { "MaxPosition", maxPosition.ToString() }, + { "Enabled", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDArray array = response["Scenes"] as OSDArray; + if (array != null) + { + for (int i = 0; i < array.Count; i++) + { + GridRegion region = ResponseToGridRegion(array[i] as OSDMap); + if (region != null) + foundRegions.Add(region); + } + } + } + + return foundRegions; + } + + public List GetDefaultRegions(UUID scopeID) + { + // TODO: Allow specifying the default grid location + const int DEFAULT_X = 1000 * 256; + const int DEFAULT_Y = 1000 * 256; + + GridRegion defRegion = GetNearestRegion(new Vector3d(DEFAULT_X, DEFAULT_Y, 0.0), true); + if (defRegion != null) + return new List(1) { defRegion }; + else + return new List(0); + } + + public List GetFallbackRegions(UUID scopeID, int x, int y) + { + GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true); + if (defRegion != null) + return new List(1) { defRegion }; + else + return new List(0); + } + + public int GetRegionFlags(UUID scopeID, UUID regionID) + { + const int REGION_ONLINE = 4; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScene" }, + { "SceneID", regionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return response["Enabled"].AsBoolean() ? REGION_ONLINE : 0; + } + else + { + m_log.Warn("[GRID CONNECTOR]: Grid service did not find a match for region " + regionID + " during region flags check"); + return -1; + } + } + + #endregion IGridService + + private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetScene" }, + { "Position", position.ToString() }, + { "FindClosest", "1" } + }; + if (onlyEnabled) + requestArgs["Enabled"] = "1"; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + return ResponseToGridRegion(response); + } + else + { + m_log.Warn("[GRID CONNECTOR]: Grid service did not find a match for region at " + position); + return null; + } + } + + private GridRegion ResponseToGridRegion(OSDMap response) + { + if (response == null) + return null; + + OSDMap extraData = response["ExtraData"] as OSDMap; + if (extraData == null) + return null; + + GridRegion region = new GridRegion(); + + region.RegionID = response["SceneID"].AsUUID(); + region.RegionName = response["Name"].AsString(); + + Vector3d minPosition = response["MinPosition"].AsVector3d(); + region.RegionLocX = (int)minPosition.X; + region.RegionLocY = (int)minPosition.Y; + + Uri httpAddress = response["Address"].AsUri(); + region.ExternalHostName = httpAddress.Host; + region.HttpPort = (uint)httpAddress.Port; + + region.ServerURI = extraData["ServerURI"].AsString(); + + IPAddress internalAddress; + IPAddress.TryParse(extraData["InternalAddress"].AsString(), out internalAddress); + if (internalAddress == null) + internalAddress = IPAddress.Any; + + region.InternalEndPoint = new IPEndPoint(internalAddress, extraData["InternalPort"].AsInteger()); + region.TerrainImage = extraData["MapTexture"].AsUUID(); + region.Access = (byte)extraData["Access"].AsInteger(); + region.RegionSecret = extraData["RegionSecret"].AsString(); + region.EstateOwner = extraData["EstateOwner"].AsUUID(); + region.Token = extraData["Token"].AsString(); + + return region; + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs new file mode 100644 index 0000000..c812899 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -0,0 +1,880 @@ +/* + * 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.Collections.Specialized; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Permissions bitflags + /// + [Flags] + public enum PermissionMask : uint + { + None = 0, + Transfer = 1 << 13, + Modify = 1 << 14, + Copy = 1 << 15, + Move = 1 << 19, + Damage = 1 << 20, + All = 0x7FFFFFFF + } + + /// + /// Connects avatar inventories to the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + private string m_userServerUrl = String.Empty; + private object m_gestureSyncRoot = new object(); + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianInventoryServiceConnector() { } + public string Name { get { return "SimianInventoryServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianInventoryServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["InventoryService"]; + if (gridConfig == null) + { + m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); + throw new Exception("Inventory connector init error"); + } + + string serviceUrl = gridConfig.GetString("InventoryServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService"); + throw new Exception("Inventory connector init error"); + } + + // FIXME: Get the user server URL too + + m_serverUrl = serviceUrl; + } + + /// + /// Create the entire inventory for a given user + /// + /// + /// + public bool CreateUserInventory(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddInventory" }, + { "OwnerID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[INVENTORY CONNECTOR]: Inventory creation for " + userID + " failed: " + response["Message"].AsString()); + + return success; + } + + /// + /// Gets the skeleton of the inventory -- folders only + /// + /// + /// + public List GetInventorySkeleton(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", userID.ToString() }, + { "OwnerID", userID.ToString() }, + { "IncludeFolders", "1" }, + { "IncludeItems", "0" }, + { "ChildrenOnly", "0" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + OSDArray items = (OSDArray)response["Items"]; + return GetFoldersFromResponse(items, userID, true); + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID + ": " + + response["Message"].AsString()); + return new List(0); + } + } + + /// + /// Synchronous inventory fetch. + /// + /// + /// + [Obsolete] + public InventoryCollection GetUserInventory(UUID userID) + { + m_log.Error("[INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID); + + InventoryCollection inventory = new InventoryCollection(); + inventory.UserID = userID; + inventory.Folders = new List(); + inventory.Items = new List(); + + return inventory; + } + + /// + /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the + /// inventory has been received + /// + /// + /// + [Obsolete] + public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) + { + m_log.Error("[INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID); + callback(new List(0), new List(0)); + } + + /// + /// Retrieve the root inventory folder for the given user. + /// + /// + /// null if no root folder was found + public InventoryFolderBase GetRootFolder(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", userID.ToString() }, + { "OwnerID", userID.ToString() }, + { "IncludeFolders", "1" }, + { "IncludeItems", "0" }, + { "ChildrenOnly", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + OSDArray items = (OSDArray)response["Items"]; + List folders = GetFoldersFromResponse(items, userID, true); + + if (folders.Count > 0) + return folders[0]; + } + + return null; + } + + /// + /// Gets the user folder for the given folder-type + /// + /// + /// + /// + public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) + { + string contentType = SLUtil.SLAssetTypeToContentType((int)type); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetFolderForType" }, + { "ContentType", contentType }, + { "OwnerID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Folder"] is OSDMap) + { + OSDMap folder = (OSDMap)response["Folder"]; + + return new InventoryFolderBase( + folder["ID"].AsUUID(), + folder["Name"].AsString(), + folder["OwnerID"].AsUUID(), + (short)SLUtil.ContentTypeToSLAssetType(folder["ContentType"].AsString()), + folder["ParentID"].AsUUID(), + (ushort)folder["Version"].AsInteger() + ); + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: Default folder not found for content type " + contentType); + return GetRootFolder(userID); + } + } + + /// + /// Get an item, given by its UUID + /// + /// + /// + public InventoryItemBase GetItem(InventoryItemBase item) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", item.ID.ToString() }, + { "OwnerID", item.Owner.ToString() }, + { "IncludeFolders", "1" }, + { "IncludeItems", "1" }, + { "ChildrenOnly", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + List items = GetItemsFromResponse((OSDArray)response["Items"]); + if (items.Count > 0) + { + // The requested item should be the first in this list, but loop through + // and sanity check just in case + for (int i = 0; i < items.Count; i++) + { + if (items[i].ID == item.ID) + return items[i]; + } + } + } + + m_log.Warn("[INVENTORY CONNECTOR]: Item " + item.ID + " owned by " + item.Owner + " not found"); + return null; + } + + /// + /// Get a folder, given by its UUID + /// + /// + /// + public InventoryFolderBase GetFolder(InventoryFolderBase folder) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", folder.ID.ToString() }, + { "OwnerID", folder.Owner.ToString() }, + { "IncludeFolders", "1" }, + { "IncludeItems", "0" }, + { "ChildrenOnly", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + OSDArray items = (OSDArray)response["Items"]; + List folders = GetFoldersFromResponse(items, folder.ID, true); + + if (folders.Count > 0) + return folders[0]; + } + + return null; + } + + /// + /// Gets everything (folders and items) inside a folder + /// + /// + /// + /// + public InventoryCollection GetFolderContent(UUID userID, UUID folderID) + { + InventoryCollection inventory = new InventoryCollection(); + inventory.UserID = userID; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", folderID.ToString() }, + { "OwnerID", userID.ToString() }, + { "IncludeFolders", "1" }, + { "IncludeItems", "1" }, + { "ChildrenOnly", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + OSDArray items = (OSDArray)response["Items"]; + + inventory.Folders = GetFoldersFromResponse(items, folderID, false); + inventory.Items = GetItemsFromResponse(items); + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: Error fetching folder " + folderID + " content for " + userID + ": " + + response["Message"].AsString()); + inventory.Folders = new List(0); + inventory.Items = new List(0); + } + + return inventory; + } + + /// + /// Gets the items inside a folder + /// + /// + /// + /// + public List GetFolderItems(UUID userID, UUID folderID) + { + InventoryCollection inventory = new InventoryCollection(); + inventory.UserID = userID; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNode" }, + { "ItemID", folderID.ToString() }, + { "OwnerID", userID.ToString() }, + { "IncludeFolders", "0" }, + { "IncludeItems", "1" }, + { "ChildrenOnly", "1" } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["Items"] is OSDArray) + { + OSDArray items = (OSDArray)response["Items"]; + return GetItemsFromResponse(items); + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: Error fetching folder " + folderID + " for " + userID + ": " + + response["Message"].AsString()); + return new List(0); + } + } + + /// + /// Add a new folder to the user's inventory + /// + /// + /// true if the folder was successfully added + public bool AddFolder(InventoryFolderBase folder) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddInventoryFolder" }, + { "FolderID", folder.ID.ToString() }, + { "ParentID", folder.ParentID.ToString() }, + { "OwnerID", folder.Owner.ToString() }, + { "Name", folder.Name }, + { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + { + m_log.Warn("[INVENTORY CONNECTOR]: Error creating folder " + folder.Name + " for " + folder.Owner + ": " + + response["Message"].AsString()); + } + + return success; + } + + /// + /// Update a folder in the user's inventory + /// + /// + /// true if the folder was successfully updated + public bool UpdateFolder(InventoryFolderBase folder) + { + return AddFolder(folder); + } + + /// + /// Move an inventory folder to a new location + /// + /// A folder containing the details of the new location + /// true if the folder was successfully moved + public bool MoveFolder(InventoryFolderBase folder) + { + return AddFolder(folder); + } + + /// + /// Delete an item from the user's inventory + /// + /// + /// true if the item was successfully deleted + //bool DeleteItem(InventoryItemBase item); + public bool DeleteFolders(UUID userID, List folderIDs) + { + return DeleteItems(userID, folderIDs); + } + + /// + /// Delete an item from the user's inventory + /// + /// + /// true if the item was successfully deleted + public bool DeleteItems(UUID userID, List itemIDs) + { + // TODO: RemoveInventoryNode should be replaced with RemoveInventoryNodes + bool allSuccess = true; + + for (int i = 0; i < itemIDs.Count; i++) + { + UUID itemID = itemIDs[i]; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveInventoryNode" }, + { "OwnerID", userID.ToString() }, + { "ItemID", itemID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + { + m_log.Warn("[INVENTORY CONNECTOR]: Error removing item " + itemID + " for " + userID + ": " + + response["Message"].AsString()); + allSuccess = false; + } + } + + return allSuccess; + } + + /// + /// Purge an inventory folder of all its items and subfolders. + /// + /// + /// true if the folder was successfully purged + public bool PurgeFolder(InventoryFolderBase folder) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "PurgeInventoryFolder" }, + { "OwnerID", folder.Owner.ToString() }, + { "FolderID", folder.ID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + { + m_log.Warn("[INVENTORY CONNECTOR]: Error purging folder " + folder.ID + " for " + folder.Owner + ": " + + response["Message"].AsString()); + } + + return success; + } + + /// + /// Add a new item to the user's inventory + /// + /// + /// true if the item was successfully added + public bool AddItem(InventoryItemBase item) + { + // A folder of UUID.Zero means we need to find the most appropriate home for this item + if (item.Folder == UUID.Zero) + { + InventoryFolderBase folder = GetFolderForType(item.Owner, (AssetType)item.AssetType); + if (folder != null && folder.ID != UUID.Zero) + item.Folder = folder.ID; + else + item.Folder = item.Owner; // Root folder + } + + if ((AssetType)item.AssetType == AssetType.Gesture) + UpdateGesture(item.Owner, item.ID, item.Flags == 1); + + if (item.BasePermissions == 0) + m_log.WarnFormat("[INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID); + + OSDMap permissions = new OSDMap + { + { "BaseMask", OSD.FromInteger(item.BasePermissions) }, + { "EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) }, + { "GroupMask", OSD.FromInteger(item.GroupPermissions) }, + { "NextOwnerMask", OSD.FromInteger(item.NextPermissions) }, + { "OwnerMask", OSD.FromInteger(item.CurrentPermissions) } + }; + + OSDMap extraData = new OSDMap() + { + { "Flags", OSD.FromInteger(item.Flags) }, + { "GroupID", OSD.FromUUID(item.GroupID) }, + { "GroupOwned", OSD.FromBoolean(item.GroupOwned) }, + { "SalePrice", OSD.FromInteger(item.SalePrice) }, + { "SaleType", OSD.FromInteger(item.SaleType) }, + { "Permissions", permissions } + }; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddInventoryItem" }, + { "ItemID", item.ID.ToString() }, + { "AssetID", item.AssetID.ToString() }, + { "ParentID", item.Folder.ToString() }, + { "OwnerID", item.Owner.ToString() }, + { "Name", item.Name }, + { "Description", item.Description }, + { "CreatorID", item.CreatorId }, + { "ExtraData", OSDParser.SerializeJsonString(extraData) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + { + m_log.Warn("[INVENTORY CONNECTOR]: Error creating item " + item.Name + " for " + item.Owner + ": " + + response["Message"].AsString()); + } + + return success; + } + + /// + /// Update an item in the user's inventory + /// + /// + /// true if the item was successfully updated + public bool UpdateItem(InventoryItemBase item) + { + if (item.AssetID != UUID.Zero) + { + return AddItem(item); + } + else + { + // This is actually a folder update + InventoryFolderBase folder = new InventoryFolderBase(item.ID, item.Name, item.Owner, (short)item.AssetType, item.Folder, 0); + return UpdateFolder(folder); + } + } + + public bool MoveItems(UUID ownerID, List items) + { + bool success = true; + + while (items.Count > 0) + { + List currentItems = new List(); + UUID destFolderID = items[0].Folder; + + // Find all of the items being moved to the current destination folder + for (int i = 0; i < items.Count; i++) + { + InventoryItemBase item = items[i]; + if (item.Folder == destFolderID) + currentItems.Add(item); + } + + // Do the inventory move for the current items + success &= MoveItems(ownerID, items, destFolderID); + + // Remove the processed items from the list + for (int i = 0; i < currentItems.Count; i++) + items.Remove(currentItems[i]); + } + + return success; + } + + /// + /// Does the given user have an inventory structure? + /// + /// + /// + public bool HasInventoryForUser(UUID userID) + { + return GetRootFolder(userID) != null; + } + + /// + /// Get the active gestures of the agent. + /// + /// + /// + public List GetActiveGestures(UUID userID) + { + OSDArray items = FetchGestures(userID); + + string[] itemIDs = new string[items.Count]; + for (int i = 0; i < items.Count; i++) + itemIDs[i] = items[i].AsUUID().ToString(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNodes" }, + { "OwnerID", userID.ToString() }, + { "Items", String.Join(",", itemIDs) } + }; + + // FIXME: Implement this in SimianGrid + return new List(0); + } + + /// + /// Get the union of permissions of all inventory items + /// that hold the given assetID. + /// + /// + /// + /// The permissions or 0 if no such asset is found in + /// the user's inventory + public int GetAssetPermissions(UUID userID, UUID assetID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetInventoryNodes" }, + { "OwnerID", userID.ToString() }, + { "AssetID", assetID.ToString() } + }; + + // FIXME: Implement this in SimianGrid + return (int)PermissionMask.All; + } + + private List GetFoldersFromResponse(OSDArray items, UUID baseFolder, bool includeBaseFolder) + { + List invFolders = new List(items.Count); + + for (int i = 0; i < items.Count; i++) + { + OSDMap item = items[i] as OSDMap; + + if (item != null && item["Type"].AsString() == "Folder") + { + UUID folderID = item["ID"].AsUUID(); + + if (folderID == baseFolder && !includeBaseFolder) + continue; + + invFolders.Add(new InventoryFolderBase( + folderID, + item["Name"].AsString(), + item["OwnerID"].AsUUID(), + (short)SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()), + item["ParentID"].AsUUID(), + (ushort)item["Version"].AsInteger() + )); + } + } + + return invFolders; + } + + private List GetItemsFromResponse(OSDArray items) + { + List invItems = new List(items.Count); + + for (int i = 0; i < items.Count; i++) + { + OSDMap item = items[i] as OSDMap; + + if (item != null && item["Type"].AsString() == "Item") + { + InventoryItemBase invItem = new InventoryItemBase(); + + invItem.AssetID = item["AssetID"].AsUUID(); + invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()); + invItem.CreationDate = item["CreationDate"].AsInteger(); + invItem.CreatorId = item["CreatorID"].AsString(); + invItem.CreatorIdAsUuid = item["CreatorID"].AsUUID(); + invItem.Description = item["Description"].AsString(); + invItem.Folder = item["ParentID"].AsUUID(); + invItem.ID = item["ID"].AsUUID(); + invItem.InvType = SLUtil.ContentTypeToSLInvType(item["ContentType"].AsString()); + invItem.Name = item["Name"].AsString(); + invItem.Owner = item["OwnerID"].AsUUID(); + + OSDMap extraData = item["ExtraData"] as OSDMap; + if (extraData != null && extraData.Count > 0) + { + invItem.Flags = extraData["Flags"].AsUInteger(); + invItem.GroupID = extraData["GroupID"].AsUUID(); + invItem.GroupOwned = extraData["GroupOwned"].AsBoolean(); + invItem.SalePrice = extraData["SalePrice"].AsInteger(); + invItem.SaleType = (byte)extraData["SaleType"].AsInteger(); + + OSDMap perms = extraData["Permissions"] as OSDMap; + if (perms != null) + { + invItem.BasePermissions = perms["BaseMask"].AsUInteger(); + invItem.CurrentPermissions = perms["OwnerMask"].AsUInteger(); + invItem.EveryOnePermissions = perms["EveryoneMask"].AsUInteger(); + invItem.GroupPermissions = perms["GroupMask"].AsUInteger(); + invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger(); + } + } + + if (invItem.BasePermissions == 0) + { + m_log.InfoFormat("[INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})", + invItem.Name, invItem.ID); + invItem.BasePermissions = (uint)PermissionMask.All; + invItem.CurrentPermissions = (uint)PermissionMask.All; + invItem.EveryOnePermissions = (uint)PermissionMask.All; + invItem.GroupPermissions = (uint)PermissionMask.All; + invItem.NextPermissions = (uint)PermissionMask.All; + } + + invItems.Add(invItem); + } + } + + return invItems; + } + + private bool MoveItems(UUID ownerID, List items, UUID destFolderID) + { + string[] itemIDs = new string[items.Count]; + for (int i = 0; i < items.Count; i++) + itemIDs[i] = items[i].ID.ToString(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "MoveInventoryNodes" }, + { "OwnerID", ownerID.ToString() }, + { "FolderID", destFolderID.ToString() }, + { "Items", String.Join(",", itemIDs) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + { + m_log.Warn("[INVENTORY CONNECTOR]: Failed to move " + items.Count + " items to " + + destFolderID + ": " + response["Message"].AsString()); + } + + return success; + } + + private void UpdateGesture(UUID userID, UUID itemID, bool enabled) + { + OSDArray gestures = FetchGestures(userID); + OSDArray newGestures = new OSDArray(); + + for (int i = 0; i < gestures.Count; i++) + { + UUID gesture = gestures[i].AsUUID(); + if (gesture != itemID) + newGestures.Add(OSD.FromUUID(gesture)); + } + + if (enabled) + newGestures.Add(OSD.FromUUID(itemID)); + + SaveGestures(userID, newGestures); + } + + private OSDArray FetchGestures(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDMap user = response["User"] as OSDMap; + if (user != null && response.ContainsKey("Gestures")) + { + OSD gestures = OSDParser.DeserializeJson(response["Gestures"].AsString()); + if (gestures != null && gestures is OSDArray) + return (OSDArray)gestures; + else + m_log.Error("[INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID); + } + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID + ": " + + response["Message"].AsString()); + } + + return new OSDArray(); + } + + private void SaveGestures(UUID userID, OSDArray gestures) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "Gestures", OSDParser.SerializeJsonString(gestures) } + }; + + OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); + if (!response["Success"].AsBoolean()) + { + m_log.Warn("[INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " + + response["Message"].AsString()); + } + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs new file mode 100644 index 0000000..65de1c5 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -0,0 +1,502 @@ +/* + * 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.Collections.Specialized; +using System.Net; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects avatar presence information (for tracking current location and + /// message routing) to the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianPresenceServiceConnector : IPresenceService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianPresenceServiceConnector() { } + public string Name { get { return "SimianPresenceServiceConnector"; } } + public void AddRegion(Scene scene) + { + scene.RegisterModuleInterface(this); + + scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; + scene.EventManager.OnNewClient += NewClientHandler; + scene.EventManager.OnSignificantClientMovement += SignificantClientMovementHandler; + + LogoutRegionAgents(scene.RegionInfo.RegionID); + } + public void RemoveRegion(Scene scene) + { + scene.UnregisterModuleInterface(this); + + scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; + scene.EventManager.OnNewClient -= NewClientHandler; + scene.EventManager.OnSignificantClientMovement -= SignificantClientMovementHandler; + + LogoutRegionAgents(scene.RegionInfo.RegionID); + } + + #endregion ISharedRegionModule + + public SimianPresenceServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["PresenceService"]; + if (gridConfig == null) + { + m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini"); + throw new Exception("Presence connector init error"); + } + + string serviceUrl = gridConfig.GetString("PresenceServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[PRESENCE CONNECTOR]: No PresenceServerURI in section PresenceService"); + throw new Exception("Presence connector init error"); + } + + m_serverUrl = serviceUrl; + } + + #region IPresenceService + + public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID) + { + m_log.ErrorFormat("[PRESENCE CONNECTOR]: Login requested, UserID={0}, SessionID={1}, SecureSessionID={2}", + userID, sessionID, secureSessionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddSession" }, + { "UserID", userID.ToString() } + }; + if (sessionID != UUID.Zero) + { + requestArgs["SessionID"] = sessionID.ToString(); + requestArgs["SecureSessionID"] = secureSessionID.ToString(); + } + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to login agent " + userID + ": " + response["Message"].AsString()); + + return success; + } + + public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookAt) + { + m_log.InfoFormat("[PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveSession" }, + { "SessionID", sessionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to logout agent with sessionID " + sessionID + ": " + response["Message"].AsString()); + + return success; + } + + public bool LogoutRegionAgents(UUID regionID) + { + m_log.InfoFormat("[PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveSessions" }, + { "SceneID", regionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to logout agents from region " + regionID + ": " + response["Message"].AsString()); + + return success; + } + + public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) + { + //m_log.DebugFormat("[PRESENCE CONNECTOR]: Updating session data for agent with sessionID " + sessionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "UpdateSession" }, + { "SessionID", sessionID.ToString() }, + { "SceneID", regionID.ToString() }, + { "ScenePosition", position.ToString() }, + { "SceneLookAt", lookAt.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to update agent session " + sessionID + ": " + response["Message"].AsString()); + + return success; + } + + public PresenceInfo GetAgent(UUID sessionID) + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSession" }, + { "SessionID", sessionID.ToString() } + }; + + OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs); + if (sessionResponse["Success"].AsBoolean()) + { + UUID userID = sessionResponse["UserID"].AsUUID(); + m_log.DebugFormat("[PRESENCE CONNECTOR]: Requesting user data for " + userID); + + requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); + if (userResponse["Success"].AsBoolean()) + return ResponseToPresenceInfo(sessionResponse, userResponse); + else + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); + } + else + { + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString()); + } + + return null; + } + + public PresenceInfo[] GetAgents(string[] userIDs) + { + List presences = new List(userIDs.Length); + + for (int i = 0; i < userIDs.Length; i++) + { + UUID userID; + if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero) + presences.AddRange(GetSessions(userID)); + } + + return presences.ToArray(); + } + + public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Setting home location for user " + userID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "HomeLocation", SerializeLocation(regionID, position, lookAt) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to set home location for " + userID + ": " + response["Message"].AsString()); + + return success; + } + + #endregion IPresenceService + + #region Presence Detection + + private void MakeRootAgentHandler(ScenePresence sp) + { + m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); + + ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + SetLastLocation(sp.UUID, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + } + + private void NewClientHandler(IClientAPI client) + { + client.OnConnectionClosed += LogoutHandler; + } + + private void SignificantClientMovementHandler(IClientAPI client) + { + ScenePresence sp; + if (client.Scene is Scene && ((Scene)client.Scene).TryGetAvatar(client.AgentId, out sp)) + ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + } + + private void LogoutHandler(IClientAPI client) + { + if (client.IsLoggingOut) + { + client.OnConnectionClosed -= LogoutHandler; + + object obj; + if (client.Scene.TryGetAvatar(client.AgentId, out obj) && obj is ScenePresence) + { + // The avatar is still in the scene, we can get the exact logout position + ScenePresence sp = (ScenePresence)obj; + SetLastLocation(client.AgentId, client.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + } + else + { + // The avatar was already removed from the scene, store LastLocation using the most recent session data + m_log.Warn("[PRESENCE]: " + client.Name + " has already been removed from the scene, storing approximate LastLocation"); + SetLastLocation(client.SessionId); + } + + LogoutAgent(client.SessionId, Vector3.Zero, Vector3.UnitX); + } + } + + #endregion Presence Detection + + #region Helpers + + private OSDMap GetUserData(UUID userID) + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Requesting user data for " + userID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["User"] is OSDMap) + return response; + else + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString()); + + return null; + } + + private OSDMap GetSessionData(UUID sessionID) + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Requesting session data for session " + sessionID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSession" }, + { "SessionID", sessionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + return response; + else + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve session data for session " + sessionID); + + return null; + } + + private List GetSessions(UUID userID) + { + List presences = new List(1); + + OSDMap userResponse = GetUserData(userID); + if (userResponse != null) + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Requesting sessions for " + userID); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSession" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + PresenceInfo presence = ResponseToPresenceInfo(response, userResponse); + if (presence != null) + presences.Add(presence); + } + else + { + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve sessions for " + userID + ": " + response["Message"].AsString()); + } + } + + return presences; + } + + /// + /// Fetch the last known avatar location with GetSession and persist it + /// as user data with AddUserData + /// + private bool SetLastLocation(UUID sessionID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSession" }, + { "SessionID", sessionID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (success) + { + UUID userID = response["UserID"].AsUUID(); + UUID sceneID = response["SceneID"].AsUUID(); + Vector3 position = response["ScenePosition"].AsVector3(); + Vector3 lookAt = response["SceneLookAt"].AsVector3(); + + return SetLastLocation(userID, sceneID, position, lookAt); + } + else + { + m_log.Warn("[PRESENCE CONNECTOR]: Failed to retrieve presence information for session " + sessionID + + " while saving last location: " + response["Message"].AsString()); + } + + return success; + } + + private bool SetLastLocation(UUID userID, UUID sceneID, Vector3 position, Vector3 lookAt) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "LastLocation", SerializeLocation(sceneID, position, lookAt) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.Warn("[PRESENCE CONNECTOR]: Failed to set last location for " + userID + ": " + response["Message"].AsString()); + + return success; + } + + private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) + { + if (sessionResponse == null) + return null; + + PresenceInfo info = new PresenceInfo(); + + info.Online = true; + info.UserID = sessionResponse["UserID"].AsUUID().ToString(); + info.RegionID = sessionResponse["SceneID"].AsUUID(); + info.Position = sessionResponse["ScenePosition"].AsVector3(); + info.LookAt = sessionResponse["SceneLookAt"].AsVector3(); + + if (userResponse != null && userResponse["User"] is OSDMap) + { + OSDMap user = (OSDMap)userResponse["User"]; + + info.Login = user["LastLoginDate"].AsDate(); + info.Logout = user["LastLogoutDate"].AsDate(); + DeserializeLocation(user["HomeLocation"].AsString(), out info.HomeRegionID, out info.HomePosition, out info.HomeLookAt); + } + + return info; + } + + private string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt) + { + return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}"; + } + + private bool DeserializeLocation(string location, out UUID regionID, out Vector3 position, out Vector3 lookAt) + { + OSDMap map = null; + + try { map = OSDParser.DeserializeJson(location) as OSDMap; } + catch { } + + if (map != null) + { + regionID = map["SceneID"].AsUUID(); + if (Vector3.TryParse(map["Position"].AsString(), out position) && + Vector3.TryParse(map["LookAt"].AsString(), out lookAt)) + { + return true; + } + } + + regionID = UUID.Zero; + position = Vector3.Zero; + lookAt = Vector3.Zero; + return false; + } + + #endregion Helpers + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs new file mode 100644 index 0000000..1e19982 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -0,0 +1,432 @@ +/* + * 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.Collections.Specialized; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Avatar profile flags + /// + [Flags] + public enum ProfileFlags : uint + { + AllowPublish = 1, + MaturePublish = 2, + Identified = 4, + Transacted = 8, + Online = 16 + } + + /// + /// Connects avatar profile and classified queries to the SimianGrid + /// backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianProfiles : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + + #region INonSharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void Close() { } + + public SimianProfiles() { } + public string Name { get { return "SimianProfiles"; } } + public void AddRegion(Scene scene) { CheckEstateManager(scene); scene.EventManager.OnClientConnect += ClientConnectHandler; } + public void RemoveRegion(Scene scene) { scene.EventManager.OnClientConnect -= ClientConnectHandler; } + + #endregion INonSharedRegionModule + + public SimianProfiles(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["UserAccountService"]; + if (gridConfig == null) + { + m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini"); + throw new Exception("Profiles init error"); + } + + string serviceUrl = gridConfig.GetString("UserAccountServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[PROFILES]: No UserAccountServerURI in section UserAccountService"); + throw new Exception("Profiles init error"); + } + + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; + + m_serverUrl = serviceUrl; + } + + private void ClientConnectHandler(IClientCore clientCore) + { + if (clientCore is IClientAPI) + { + IClientAPI client = (IClientAPI)clientCore; + + // Classifieds + client.AddGenericPacketHandler("avatarclassifiedsrequest", AvatarClassifiedsRequestHandler); + client.OnClassifiedInfoRequest += ClassifiedInfoRequestHandler; + client.OnClassifiedInfoUpdate += ClassifiedInfoUpdateHandler; + client.OnClassifiedDelete += ClassifiedDeleteHandler; + + // Picks + client.AddGenericPacketHandler("avatarpicksrequest", HandleAvatarPicksRequest); + client.AddGenericPacketHandler("pickinforequest", HandlePickInfoRequest); + client.OnPickInfoUpdate += PickInfoUpdateHandler; + client.OnPickDelete += PickDeleteHandler; + + // Notes + client.AddGenericPacketHandler("avatarnotesrequest", HandleAvatarNotesRequest); + client.OnAvatarNotesUpdate += AvatarNotesUpdateHandler; + + // Profiles + client.OnRequestAvatarProperties += RequestAvatarPropertiesHandler; + client.OnUpdateAvatarProperties += UpdateAvatarPropertiesHandler; + client.OnAvatarInterestUpdate += AvatarInterestUpdateHandler; + client.OnUserInfoRequest += UserInfoRequestHandler; + client.OnUpdateUserInfo += UpdateUserInfoHandler; + } + } + + #region Classifieds + + private void AvatarClassifiedsRequestHandler(Object sender, string method, List args) + { + if (!(sender is IClientAPI)) + return; + IClientAPI client = (IClientAPI)sender; + + UUID targetAvatarID; + if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID)) + { + m_log.Error("[PROFILES]: Unrecognized arguments for " + method); + return; + } + + // FIXME: Query the generic key/value store for classifieds + client.SendAvatarClassifiedReply(targetAvatarID, new Dictionary(0)); + } + + private void ClassifiedInfoRequestHandler(UUID classifiedID, IClientAPI client) + { + // FIXME: Fetch this info + client.SendClassifiedInfoReply(classifiedID, UUID.Zero, 0, Utils.DateTimeToUnixTime(DateTime.UtcNow + TimeSpan.FromDays(1)), + 0, String.Empty, String.Empty, UUID.Zero, 0, UUID.Zero, String.Empty, Vector3.Zero, String.Empty, 0, 0); + } + + private void ClassifiedInfoUpdateHandler(UUID classifiedID, uint category, string name, string description, + UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price, + IClientAPI client) + { + // FIXME: Save this info + } + + private void ClassifiedDeleteHandler(UUID classifiedID, IClientAPI client) + { + // FIXME: Delete the specified classified ad + } + + #endregion Classifieds + + #region Picks + + private void HandleAvatarPicksRequest(Object sender, string method, List args) + { + if (!(sender is IClientAPI)) + return; + IClientAPI client = (IClientAPI)sender; + + UUID targetAvatarID; + if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID)) + { + m_log.Error("[PROFILES]: Unrecognized arguments for " + method); + return; + } + + // FIXME: Fetch these + client.SendAvatarPicksReply(targetAvatarID, new Dictionary(0)); + } + + private void HandlePickInfoRequest(Object sender, string method, List args) + { + if (!(sender is IClientAPI)) + return; + IClientAPI client = (IClientAPI)sender; + + UUID avatarID; + UUID pickID; + if (args.Count < 2 || !UUID.TryParse(args[0], out avatarID) || !UUID.TryParse(args[1], out pickID)) + { + m_log.Error("[PROFILES]: Unrecognized arguments for " + method); + return; + } + + // FIXME: Fetch this + client.SendPickInfoReply(pickID, avatarID, false, UUID.Zero, String.Empty, String.Empty, UUID.Zero, String.Empty, + String.Empty, String.Empty, Vector3.Zero, 0, false); + } + + private void PickInfoUpdateHandler(IClientAPI client, UUID pickID, UUID creatorID, bool topPick, string name, + string desc, UUID snapshotID, int sortOrder, bool enabled) + { + // FIXME: Save this + } + + private void PickDeleteHandler(IClientAPI client, UUID pickID) + { + // FIXME: Delete + } + + #endregion Picks + + #region Notes + + private void HandleAvatarNotesRequest(Object sender, string method, List args) + { + if (!(sender is IClientAPI)) + return; + IClientAPI client = (IClientAPI)sender; + + UUID targetAvatarID; + if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID)) + { + m_log.Error("[PROFILES]: Unrecognized arguments for " + method); + return; + } + + // FIXME: Fetch this + client.SendAvatarNotesReply(targetAvatarID, String.Empty); + } + + private void AvatarNotesUpdateHandler(IClientAPI client, UUID targetID, string notes) + { + // FIXME: Save this + } + + #endregion Notes + + #region Profiles + + private void RequestAvatarPropertiesHandler(IClientAPI client, UUID avatarID) + { + OSDMap user = FetchUserData(avatarID); + + ProfileFlags flags = ProfileFlags.AllowPublish | ProfileFlags.MaturePublish; + + if (user != null) + { + OSDMap about = null; + if (user.ContainsKey("LLAbout")) + { + try { about = OSDParser.DeserializeJson(user["LLAbout"].AsString()) as OSDMap; } + catch { } + } + + if (about == null) + about = new OSDMap(0); + + // Check if this user is a grid operator + byte[] charterMember; + if (user["AccessLevel"].AsInteger() >= 200) + charterMember = Utils.StringToBytes("Operator"); + else + charterMember = Utils.EmptyBytes; + + // Check if the user is online + if (client.Scene is Scene) + { + OpenSim.Services.Interfaces.PresenceInfo[] presences = ((Scene)client.Scene).PresenceService.GetAgents(new string[] { avatarID.ToString() }); + if (presences != null && presences.Length > 0) + flags |= ProfileFlags.Online; + } + + // Check if the user is identified + if (user["Identified"].AsBoolean()) + flags |= ProfileFlags.Identified; + + client.SendAvatarProperties(avatarID, about["About"].AsString(), user["CreationDate"].AsDate().ToString("M/d/yyyy", + System.Globalization.CultureInfo.InvariantCulture), charterMember, about["FLAbout"].AsString(), (uint)flags, + about["FLImage"].AsUUID(), about["Image"].AsUUID(), about["URL"].AsString(), user["Partner"].AsUUID()); + + } + else + { + m_log.Warn("[PROFILES]: Failed to fetch profile information for " + client.Name + ", returning default values"); + client.SendAvatarProperties(avatarID, String.Empty, "1/1/1970", Utils.EmptyBytes, + String.Empty, (uint)flags, UUID.Zero, UUID.Zero, String.Empty, UUID.Zero); + } + } + + private void UpdateAvatarPropertiesHandler(IClientAPI client, UserProfileData profileData) + { + OSDMap map = new OSDMap + { + { "About", OSD.FromString(profileData.AboutText) }, + { "Image", OSD.FromUUID(profileData.Image) }, + { "FLAbout", OSD.FromString(profileData.FirstLifeAboutText) }, + { "FLImage", OSD.FromUUID(profileData.FirstLifeImage) }, + { "URL", OSD.FromString(profileData.ProfileUrl) } + }; + + AddUserData(client.AgentId, "LLAbout", map); + } + + private void AvatarInterestUpdateHandler(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, + string skillstext, string languages) + { + OSDMap map = new OSDMap + { + { "WantMask", OSD.FromInteger(wantmask) }, + { "WantText", OSD.FromString(wanttext) }, + { "SkillsMask", OSD.FromInteger(skillsmask) }, + { "SkillsText", OSD.FromString(skillstext) }, + { "Languages", OSD.FromString(languages) } + }; + + AddUserData(client.AgentId, "LLInterests", map); + } + + private void UserInfoRequestHandler(IClientAPI client) + { + m_log.Error("[PROFILES]: UserInfoRequestHandler"); + + // Fetch this user's e-mail address + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", client.AgentId.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + string email = response["Email"].AsString(); + + if (!response["Success"].AsBoolean()) + m_log.Warn("[PROFILES]: GetUser failed during a user info request for " + client.Name); + + client.SendUserInfoReply(false, true, email); + } + + private void UpdateUserInfoHandler(bool imViaEmail, bool visible, IClientAPI client) + { + m_log.Info("[PROFILES]: Ignoring user info update from " + client.Name); + } + + #endregion Profiles + + /// + /// Sanity checks regions for a valid estate owner at startup + /// + private void CheckEstateManager(Scene scene) + { + EstateSettings estate = scene.RegionInfo.EstateSettings; + + if (estate.EstateOwner == UUID.Zero) + { + // Attempt to lookup the grid admin + UserAccount admin = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, UUID.Zero); + if (admin != null) + { + m_log.InfoFormat("[PROFILES]: Setting estate {0} (ID: {1}) owner to {2}", estate.EstateName, + estate.EstateID, admin.Name); + + estate.EstateOwner = admin.PrincipalID; + estate.Save(); + } + else + { + m_log.WarnFormat("[PROFILES]: Estate {0} (ID: {1}) does not have an owner", estate.EstateName, estate.EstateID); + } + } + } + + private bool AddUserData(UUID userID, string key, OSDMap value) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { key, OSDParser.SerializeJsonString(value) } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (!success) + m_log.WarnFormat("[PROFILES]: Failed to add user data with key {0} for {1}: {2}", key, userID, response["Message"].AsString()); + + return success; + } + + private OSDMap FetchUserData(UUID userID) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean() && response["User"] is OSDMap) + { + return (OSDMap)response["User"]; + } + else + { + m_log.Error("[PROFILES]: Failed to fetch user data for " + userID + ": " + response["Message"].AsString()); + } + + return null; + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs new file mode 100644 index 0000000..14097d0 --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -0,0 +1,307 @@ +/* + * 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.Collections.Specialized; +using System.IO; +using System.Reflection; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + /// + /// Connects user account data (creating new users, looking up existing + /// users) to the SimianGrid backend + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverUrl = String.Empty; + private ExpiringCache m_accountCache = new ExpiringCache(); + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public void RegionLoaded(Scene scene) { } + public void PostInitialise() { } + public void Close() { } + + public SimianUserAccountServiceConnector() { } + public string Name { get { return "SimianUserAccountServiceConnector"; } } + public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } + public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + + #endregion ISharedRegionModule + + public SimianUserAccountServiceConnector(IConfigSource source) + { + Initialise(source); + } + + public void Initialise(IConfigSource source) + { + IConfig assetConfig = source.Configs["UserAccountService"]; + if (assetConfig == null) + { + m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini"); + throw new Exception("User account connector init error"); + } + + string serviceURI = assetConfig.GetString("UserAccountServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[ACCOUNT CONNECTOR]: No UserAccountServerURI in section UserAccountService"); + throw new Exception("User account connector init error"); + } + + m_serverUrl = serviceURI; + } + + public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "Name", firstName + ' ' + lastName } + }; + + return GetUser(requestArgs); + } + + public UserAccount GetUserAccount(UUID scopeID, string email) + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "Email", email } + }; + + return GetUser(requestArgs); + } + + public UserAccount GetUserAccount(UUID scopeID, UUID userID) + { + // Cache check + UserAccount account; + if (m_accountCache.TryGetValue(userID, out account)) + return account; + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; + + return GetUser(requestArgs); + } + + public List GetUserAccounts(UUID scopeID, string query) + { + List accounts = new List(); + + m_log.DebugFormat("[ACCOUNT CONNECTOR]: Searching for user accounts with name query " + query); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetUsers" }, + { "NameQuery", query } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDArray array = response["Users"] as OSDArray; + if (array != null && array.Count > 0) + { + for (int i = 0; i < array.Count; i++) + { + UserAccount account = ResponseToUserAccount(array[i] as OSDMap); + if (account != null) + accounts.Add(account); + } + } + else + { + m_log.Warn("[ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format"); + } + } + else + { + m_log.Warn("[ACCOUNT CONNECTOR]: Failed to search for account data by name " + query); + } + + return accounts; + } + + public bool StoreUserAccount(UserAccount data) + { + m_log.InfoFormat("[ACCOUNT CONNECTOR]: Storing user account for " + data.Name); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUser" }, + { "UserID", data.PrincipalID.ToString() }, + { "Name", data.Name }, + { "Email", data.Email }, + { "AccessLevel", data.UserLevel.ToString() } + }; + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + + if (response["Success"].AsBoolean()) + { + m_log.InfoFormat("[ACCOUNT CONNECTOR]: Storing user account data for " + data.Name); + + requestArgs = new NameValueCollection + { + { "RequestMethod", "AddUserData" }, + { "UserID", data.PrincipalID.ToString() }, + { "CreationDate", data.Created.ToString() }, + { "UserFlags", data.UserFlags.ToString() }, + { "UserTitle", data.UserTitle } + }; + + response = WebUtil.PostToService(m_serverUrl, requestArgs); + bool success = response["Success"].AsBoolean(); + + if (success) + { + // Cache the user account info + m_accountCache.AddOrUpdate(data.PrincipalID, data, DateTime.Now + TimeSpan.FromMinutes(2.0d)); + } + else + { + m_log.Warn("[ACCOUNT CONNECTOR]: Failed to store user account data for " + data.Name + ": " + response["Message"].AsString()); + } + + return success; + } + else + { + m_log.Warn("[ACCOUNT CONNECTOR]: Failed to store user account for " + data.Name + ": " + response["Message"].AsString()); + } + + return false; + } + + /// + /// Helper method for the various ways of retrieving a user account + /// + /// Service query parameters + /// A UserAccount object on success, null on failure + private UserAccount GetUser(NameValueCollection requestArgs) + { + string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)"; + m_log.DebugFormat("[ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue); + + OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + { + OSDMap user = response["User"] as OSDMap; + if (user != null) + return ResponseToUserAccount(user); + else + m_log.Warn("[ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format"); + } + else + { + m_log.Warn("[ACCOUNT CONNECTOR]: Failed to lookup user account with query: " + lookupValue); + } + + return null; + } + + /// + /// Convert a User object in LLSD format to a UserAccount + /// + /// LLSD containing user account data + /// A UserAccount object on success, null on failure + private UserAccount ResponseToUserAccount(OSDMap response) + { + if (response == null) + return null; + + UserAccount account = new UserAccount(); + account.PrincipalID = response["UserID"].AsUUID(); + account.Created = response["CreationDate"].AsInteger(); + account.Email = response["Email"].AsString(); + account.ServiceURLs = new Dictionary(0); + account.UserFlags = response["UserFlags"].AsInteger(); + account.UserLevel = response["AccessLevel"].AsInteger(); + account.UserTitle = response["UserTitle"].AsString(); + GetFirstLastName(response["Name"].AsString(), out account.FirstName, out account.LastName); + + // Cache the user account info + m_accountCache.AddOrUpdate(account.PrincipalID, account, DateTime.Now + TimeSpan.FromMinutes(2.0d)); + + return account; + } + + /// + /// Convert a name with a single space in it to a first and last name + /// + /// A full name such as "John Doe" + /// First name + /// Last name (surname) + private static void GetFirstLastName(string name, out string firstName, out string lastName) + { + if (String.IsNullOrEmpty(name)) + { + firstName = String.Empty; + lastName = String.Empty; + } + else + { + string[] names = name.Split(' '); + + if (names.Length == 2) + { + firstName = names[0]; + lastName = names[1]; + } + else + { + firstName = String.Empty; + lastName = name; + } + } + } + } +} -- cgit v1.1 From a578feefba7d740180b8c891fc9e257dbb4ab48d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Mar 2010 20:20:38 +0000 Subject: very minor spacing adjustment --- OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index d13408d..5ee2045 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -73,7 +73,6 @@ namespace OpenSim.Framework.Servers.HttpServer /// true if the handler was successfully registered, false if a handler with the same name already existed. /// bool AddHTTPHandler(string methodName, GenericHTTPMethod handler); - bool AddPollServiceHTTPHandler(string methodName, GenericHTTPMethod handler, PollServiceEventArgs args); -- cgit v1.1 From 2313d14acbf0f23d5d041ade03fa1fe030223f51 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Mar 2010 23:33:55 +0000 Subject: minor: add some more documentation for IHttpServer.AddHTTPHandler() to tell the caller that the best match for an incoming request URI is invoked --- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 6 ++---- OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs | 6 +++++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 214f936..9a6ef77 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -202,16 +202,14 @@ namespace OpenSim.Framework.Servers.HttpServer if (!m_pollHandlers.ContainsKey(methodName)) { m_pollHandlers.Add(methodName,args); - pollHandlerResult = true; - + pollHandlerResult = true; } } if (pollHandlerResult) return AddHTTPHandler(methodName, handler); - return false; - + return false; } // Note that the agent string is provided simply to differentiate diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index 5ee2045..65b1eb5 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -47,7 +47,7 @@ namespace OpenSim.Framework.Servers.HttpServer bool AddAgentHandler(string agent, IHttpAgentHandler handler); /// - /// Add a handler for an HTTP request + /// Add a handler for an HTTP request. /// /// /// This handler can actually be invoked either as @@ -66,6 +66,10 @@ namespace OpenSim.Framework.Servers.HttpServer /// or /// /// http://localhost:9000/object/ + /// + /// In addition, the handler invoked by the HTTP server for any request is the one when best matches the request + /// URI. So if a handler for "/myapp/" is registered and a request for "/myapp/page" is received, then + /// the "/myapp/" handler is invoked if no "/myapp/page" handler exists. /// /// /// -- cgit v1.1 From ed3288a8db33be13e9e278d47cc00b3666d9d262 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 12 Mar 2010 10:16:21 -0800 Subject: Bug fix: "last location" login. --- OpenSim/Services/PresenceService/PresenceService.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index 304538a..ea8d673 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs @@ -72,6 +72,10 @@ namespace OpenSim.Services.PresenceService data.Data["HomeRegionID"] = d[0].Data["HomeRegionID"]; data.Data["HomePosition"] = d[0].Data["HomePosition"]; data.Data["HomeLookAt"] = d[0].Data["HomeLookAt"]; + data.Data["Position"] = d[0].Data["Position"]; + data.Data["LookAt"] = d[0].Data["LookAt"]; + + data.RegionID = d[0].RegionID; } else { -- cgit v1.1 From f2de50bb14bd8215ea98c79c79aabe1e6b4f2780 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 19:31:14 +0000 Subject: Fix tests broken in 88771aeed3d45e60a18aa9a810eeb37b8e5def12 Adds MockUserAccountService and connects it up Stops services being carried over between tests since this leads to hard to find bugs Improves information and error reporting when loading plugins --- .../LocalUserAccountServiceConnector.cs | 18 ++++----- .../Scenes/Tests/SceneObjectBasicTests.cs | 13 ++----- OpenSim/Server/Base/ServerUtils.cs | 40 +++++++++---------- OpenSim/Services/Interfaces/IUserAccountService.cs | 20 ++++++---- .../Tests/Common/Mock/MockUserAccountService.cs | 45 ++++++++++++++++++++++ OpenSim/Tests/Common/Mock/TestScene.cs | 4 +- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 34 ++++++++++++---- 7 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 OpenSim/Tests/Common/Mock/MockUserAccountService.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index ce0ca40..30ebb21 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -73,33 +73,31 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts IConfig userConfig = source.Configs["UserAccountService"]; if (userConfig == null) { - m_log.Error("[USER CONNECTOR]: UserAccountService missing from OpenSim.ini"); + m_log.Error("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: UserAccountService missing from OpenSim.ini"); return; } - string serviceDll = userConfig.GetString("LocalServiceModule", - String.Empty); + string serviceDll = userConfig.GetString("LocalServiceModule", String.Empty); if (serviceDll == String.Empty) { - m_log.Error("[USER CONNECTOR]: No LocalServiceModule named in section UserService"); + m_log.Error("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: No LocalServiceModule named in section UserService"); return; } Object[] args = new Object[] { source }; - m_UserService = - ServerUtils.LoadPlugin(serviceDll, - args); + m_UserService = ServerUtils.LoadPlugin(serviceDll, args); if (m_UserService == null) { - m_log.Error("[USER CONNECTOR]: Can't load user account service"); + m_log.ErrorFormat( + "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); return; } m_Enabled = true; m_Cache = new UserAccountCache(); - m_log.Info("[USER CONNECTOR]: Local user connector enabled"); + m_log.Info("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Local user connector enabled"); } } } @@ -134,6 +132,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts { if (!m_Enabled) return; + + m_log.InfoFormat("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Enabled local user accounts for region {0}", scene.RegionInfo.RegionName); } #endregion diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index b50d4ca..78f2ae3 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -86,6 +86,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void TestDeleteSceneObjectAsync() { TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001"); @@ -97,15 +98,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene); - try - { - IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId); - scene.DeRezObject(client, part.LocalId, UUID.Zero, DeRezAction.Delete, UUID.Zero); - } - catch (Exception e) - { - Console.WriteLine("Exception: " + e.StackTrace); - } + IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId); + scene.DeRezObject(client, part.LocalId, UUID.Zero, DeRezAction.Delete, UUID.Zero); + SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); Assert.That(retrievedPart, Is.Not.Null); diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index 9c54410..a399672 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -57,6 +57,12 @@ namespace OpenSim.Server.Base return ret; } + /// + /// Load a plugin from a dll with the given class or interface + /// + /// + /// The arguments which control which constructor is invoked on the plugin + /// public static T LoadPlugin(string dllName, Object[] args) where T:class { string[] parts = dllName.Split(new char[] {':'}); @@ -71,6 +77,13 @@ namespace OpenSim.Server.Base return LoadPlugin(dllName, className, args); } + /// + /// Load a plugin from a dll with the given class or interface + /// + /// + /// + /// The arguments which control which constructor is invoked on the plugin + /// public static T LoadPlugin(string dllName, string className, Object[] args) where T:class { string interfaceName = typeof(T).ToString(); @@ -83,28 +96,15 @@ namespace OpenSim.Server.Base { if (pluginType.IsPublic) { - if (className != String.Empty && - pluginType.ToString() != - pluginType.Namespace + "." + className) + if (className != String.Empty + && pluginType.ToString() != pluginType.Namespace + "." + className) continue; - Type typeInterface = - pluginType.GetInterface(interfaceName, true); + + Type typeInterface = pluginType.GetInterface(interfaceName, true); + if (typeInterface != null) { - T plug = null; - try - { - plug = (T)Activator.CreateInstance(pluginType, - args); - } - catch (Exception e) - { - if (!(e is System.MissingMethodException)) - m_log.ErrorFormat("Error loading plugin from {0}, exception {1}", dllName, e.InnerException); - return null; - } - - return plug; + return (T)Activator.CreateInstance(pluginType, args); } } } @@ -113,7 +113,7 @@ namespace OpenSim.Server.Base } catch (Exception e) { - m_log.ErrorFormat("Error loading plugin from {0}, exception {1}", dllName, e); + m_log.Error(string.Format("Error loading plugin from {0}", dllName), e); return null; } } diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index 3dacf53..a45bf8c 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -140,14 +140,20 @@ namespace OpenSim.Services.Interfaces UserAccount GetUserAccount(UUID scopeID, UUID userID); UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName); UserAccount GetUserAccount(UUID scopeID, string Email); - // Returns the list of avatars that matches both the search - // criterion and the scope ID passed - // + + /// + /// Returns the list of avatars that matches both the search criterion and the scope ID passed + /// + /// + /// + /// List GetUserAccounts(UUID scopeID, string query); - // Store the data given, wich replaces the sotred data, therefore - // must be complete. - // + /// + /// Store the data given, wich replaces the sotred data, therefore must be complete. + /// + /// + /// bool StoreUserAccount(UserAccount data); } -} +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/MockUserAccountService.cs b/OpenSim/Tests/Common/Mock/MockUserAccountService.cs new file mode 100644 index 0000000..f5d758a --- /dev/null +++ b/OpenSim/Tests/Common/Mock/MockUserAccountService.cs @@ -0,0 +1,45 @@ +/* + * 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.Collections.Generic; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Tests.Common.Mock +{ + public class MockUserAccountService : IUserAccountService + { + public MockUserAccountService(IConfigSource config) {} + + public UserAccount GetUserAccount(UUID scopeID, UUID userID) { return new UserAccount(); } + public UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName) { return new UserAccount(); } + public UserAccount GetUserAccount(UUID scopeID, string Email) { return new UserAccount(); } + public List GetUserAccounts(UUID scopeID, string query) { return new List(); } + public bool StoreUserAccount(UserAccount data) { return true; } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestScene.cs b/OpenSim/Tests/Common/Mock/TestScene.cs index 076cb7a..01f2c14 100644 --- a/OpenSim/Tests/Common/Mock/TestScene.cs +++ b/OpenSim/Tests/Common/Mock/TestScene.cs @@ -65,6 +65,6 @@ namespace OpenSim.Tests.Common.Mock public AsyncSceneObjectGroupDeleter SceneObjectGroupDeleter { get { return m_asyncSceneObjectDeleter; } - } + } } -} +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 9e718f6..ab3e7cb 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -128,7 +128,7 @@ namespace OpenSim.Tests.Common.Setup /// Starts real inventory and asset services, as opposed to mock ones, if true /// public static TestScene SetupScene( - string name, UUID id, uint x, uint y, String realServices) + string name, UUID id, uint x, uint y, String realServices) { bool newScene = false; @@ -179,15 +179,16 @@ namespace OpenSim.Tests.Common.Setup StartAssetService(testScene, true); else StartAssetService(testScene, false); + if (realServices.Contains("inventory")) StartInventoryService(testScene, true); else StartInventoryService(testScene, false); + if (realServices.Contains("grid")) StartGridService(testScene, true); - if (realServices.Contains("useraccounts")) - StartUserAccountService(testScene, true); - + + StartUserAccountService(testScene, realServices.Contains("useraccounts")); } // If not, make sure the shared module gets references to this new scene else @@ -196,9 +197,13 @@ namespace OpenSim.Tests.Common.Setup m_assetService.RegionLoaded(testScene); m_inventoryService.AddRegion(testScene); m_inventoryService.RegionLoaded(testScene); + m_userAccountService.AddRegion(testScene); + m_userAccountService.RegionLoaded(testScene); } + m_inventoryService.PostInitialise(); m_assetService.PostInitialise(); + m_userAccountService.PostInitialise(); testScene.SetModuleInterfaces(); @@ -209,6 +214,11 @@ namespace OpenSim.Tests.Common.Setup physicsPluginManager.LoadPluginsFromAssembly("Physics/OpenSim.Region.Physics.BasicPhysicsPlugin.dll"); testScene.PhysicsScene = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); + + m_assetService = null; + m_inventoryService = null; + m_gridService = null; + m_userAccountService = null; return testScene; } @@ -273,6 +283,11 @@ namespace OpenSim.Tests.Common.Setup //testScene.AddRegionModule(m_gridService.Name, m_gridService); } + /// + /// Start a user account service, whether real or mock + /// + /// + /// Starts a real service if true, a mock service if not private static void StartUserAccountService(Scene testScene, bool real) { IConfigSource config = new IniConfigSource(); @@ -280,8 +295,14 @@ namespace OpenSim.Tests.Common.Setup config.AddConfig("UserAccountService"); config.Configs["Modules"].Set("UserAccountServices", "LocalUserAccountServicesConnector"); config.Configs["UserAccountService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); + if (real) - config.Configs["UserAccountService"].Set("LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService"); + config.Configs["UserAccountService"].Set( + "LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService"); + else + config.Configs["UserAccountService"].Set( + "LocalServiceModule", "OpenSim.Tests.Common.dll:MockUserAccountService"); + if (m_userAccountService == null) { ISharedRegionModule userAccountService = new LocalUserAccountServicesConnector(); @@ -292,10 +313,9 @@ namespace OpenSim.Tests.Common.Setup // config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:TestGridService"); m_userAccountService.AddRegion(testScene); m_userAccountService.RegionLoaded(testScene); - //testScene.AddRegionModule(m_gridService.Name, m_gridService); + testScene.AddRegionModule(m_userAccountService.Name, m_userAccountService); } - /// /// Setup modules for a scene using their default settings. /// -- cgit v1.1 From aad17e751383069b799c6a78a3ac4e0ca1020a4d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 20:29:17 +0000 Subject: Simplify database setup and remove migration problems by moving all sqlite config-include settings to a separate file for standalone Update information in StandaloneCommon.ini.example to reflect this Remove ISharedRegionModule interfaces from all SimianGrid connector classes temporarily since this stopped standalone from working (due to absence of AssetURI settings, etc.). Solution here may be to create separate region module connectors as done by local/grid/hypergrid so that loading can be controlled via include files Or otherwise work out how to stop these modules from being loaded for all OpenSim invocations --- OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs | 2 +- .../Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs | 2 +- OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs | 2 +- .../Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs | 2 +- OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs | 2 +- .../Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs | 2 +- .../Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs | 2 +- OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs | 2 +- .../Connectors/SimianGrid/SimianUserAccountServiceConnector.cs | 2 +- OpenSim/Tests/Common/Mock/MockUserAccountService.cs | 1 + OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 3 +++ 11 files changed, 13 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 9fb7723..201bc70 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -46,7 +46,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects to the SimianGrid asset service /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule + public class SimianAssetServiceConnector : IAssetService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index ec66341..25e04d7 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -44,7 +44,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects authentication/authorization to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule + public class SimianAuthenticationServiceConnector : IAuthenticationService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 220f143..08403b9 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -48,7 +48,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects avatar appearance data to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule + public class SimianAvatarServiceConnector : IAvatarService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 3952a8c..856381d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -47,7 +47,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Stores and retrieves friend lists from the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianFriendsServiceConnector : IFriendsService, ISharedRegionModule + public class SimianFriendsServiceConnector : IFriendsService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 16819d1..c375076 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianGridServiceConnector : IGridService, ISharedRegionModule + public class SimianGridServiceConnector : IGridService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index c812899..9879295 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -61,7 +61,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects avatar inventories to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule + public class SimianInventoryServiceConnector : IInventoryService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 65de1c5..45d1824 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// message routing) to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianPresenceServiceConnector : IPresenceService, ISharedRegionModule + public class SimianPresenceServiceConnector : IPresenceService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index 1e19982..32f17ae 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -60,7 +60,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianProfiles : INonSharedRegionModule + public class SimianProfiles { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 14097d0..708ced3 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -47,7 +47,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// users) to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule + public class SimianUserAccountServiceConnector : IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger( diff --git a/OpenSim/Tests/Common/Mock/MockUserAccountService.cs b/OpenSim/Tests/Common/Mock/MockUserAccountService.cs index f5d758a..0769c7a 100644 --- a/OpenSim/Tests/Common/Mock/MockUserAccountService.cs +++ b/OpenSim/Tests/Common/Mock/MockUserAccountService.cs @@ -34,6 +34,7 @@ namespace OpenSim.Tests.Common.Mock { public class MockUserAccountService : IUserAccountService { + public MockUserAccountService(IConfigSource config) {} public UserAccount GetUserAccount(UUID scopeID, UUID userID) { return new UserAccount(); } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index ab3e7cb..864e2aa 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -215,6 +215,9 @@ namespace OpenSim.Tests.Common.Setup testScene.PhysicsScene = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); + // It's really not a good idea to use static variables as they carry over between tests, leading to + // problems that are extremely hard to debug. Really, these static fields need to be eliminated - + // tests using multiple regions that need to share modules need to find another solution. m_assetService = null; m_inventoryService = null; m_gridService = null; -- cgit v1.1 From 0b5141d45bcd409544e909aedabc3e58e6a86a13 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 12 Mar 2010 13:16:44 -0800 Subject: Fixed SimianGrid connectors to gracefully exit if the required config sections are missing --- .../SimianGrid/SimianAssetServiceConnector.cs | 12 ++++---- .../SimianAuthenticationServiceConnector.cs | 10 +++---- .../SimianGrid/SimianAvatarServiceConnector.cs | 10 +++---- .../SimianGrid/SimianFriendsServiceConnector.cs | 10 +++---- .../SimianGrid/SimianGridServiceConnector.cs | 10 +++---- .../SimianGrid/SimianInventoryServiceConnector.cs | 10 +++---- .../SimianGrid/SimianPresenceServiceConnector.cs | 32 +++++++++++++--------- .../Connectors/SimianGrid/SimianProfiles.cs | 12 ++++---- .../SimianUserAccountServiceConnector.cs | 13 +++++---- 9 files changed, 63 insertions(+), 56 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 201bc70..89aa911 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -46,7 +46,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects to the SimianGrid asset service /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAssetServiceConnector : IAssetService + public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -73,9 +73,9 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAssetServiceConnector() { } public string Name { get { return "SimianAssetServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } - + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } + #endregion ISharedRegionModule public SimianAssetServiceConnector(IConfigSource source) @@ -88,8 +88,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["AssetService"]; if (gridConfig == null) { - m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini"); - throw new Exception("Asset connector init error"); + m_log.Info("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini, skipping SimianAssetServiceConnector"); + return; } string serviceUrl = gridConfig.GetString("AssetServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 25e04d7..55aca36 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -44,7 +44,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects authentication/authorization to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAuthenticationServiceConnector : IAuthenticationService + public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -61,8 +61,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAuthenticationServiceConnector() { } public string Name { get { return "SimianAuthenticationServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -76,8 +76,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["AuthenticationService"]; if (assetConfig == null) { - m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini"); - throw new Exception("Authentication connector init error"); + m_log.Info("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini, skipping SimianAuthenticationServiceConnector"); + return; } string serviceURI = assetConfig.GetString("AuthenticationServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 08403b9..b5cef0c 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -48,7 +48,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects avatar appearance data to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianAvatarServiceConnector : IAvatarService + public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -66,8 +66,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAvatarServiceConnector() { } public string Name { get { return "SimianAvatarServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -81,8 +81,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["AvatarService"]; if (gridConfig == null) { - m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini"); - throw new Exception("Avatar connector init error"); + m_log.Info("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini, skipping SimianAvatarServiceConnector"); + return; } string serviceUrl = gridConfig.GetString("AvatarServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 856381d..a569e91 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -47,7 +47,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Stores and retrieves friend lists from the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianFriendsServiceConnector : IFriendsService + public class SimianFriendsServiceConnector : IFriendsService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -64,8 +64,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianFriendsServiceConnector() { } public string Name { get { return "SimianFriendsServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -79,8 +79,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["FriendsService"]; if (assetConfig == null) { - m_log.Error("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini"); - throw new Exception("Friends connector init error"); + m_log.Info("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini, skipping SimianFriendsServiceConnector"); + return; } string serviceURI = assetConfig.GetString("FriendsServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index c375076..2e600f0 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianGridServiceConnector : IGridService + public class SimianGridServiceConnector : IGridService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -68,8 +68,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianGridServiceConnector() { } public string Name { get { return "SimianGridServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -83,8 +83,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["GridService"]; if (gridConfig == null) { - m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); - throw new Exception("Grid connector init error"); + m_log.Info("[GRID CONNECTOR]: GridService missing from OpenSim.ini, skipping SimianGridServiceConnector"); + return; } string serviceUrl = gridConfig.GetString("GridServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 9879295..a50ecbc 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -61,7 +61,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// Connects avatar inventories to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianInventoryServiceConnector : IInventoryService + public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -80,8 +80,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianInventoryServiceConnector() { } public string Name { get { return "SimianInventoryServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -95,8 +95,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["InventoryService"]; if (gridConfig == null) { - m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); - throw new Exception("Inventory connector init error"); + m_log.Info("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini, skipping SimianInventoryServiceConnector"); + return; } string serviceUrl = gridConfig.GetString("InventoryServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 45d1824..542093f 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// message routing) to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianPresenceServiceConnector : IPresenceService + public class SimianPresenceServiceConnector : IPresenceService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -70,23 +70,29 @@ namespace OpenSim.Services.Connectors.SimianGrid public string Name { get { return "SimianPresenceServiceConnector"; } } public void AddRegion(Scene scene) { - scene.RegisterModuleInterface(this); + if (!String.IsNullOrEmpty(m_serverUrl)) + { + scene.RegisterModuleInterface(this); - scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; - scene.EventManager.OnNewClient += NewClientHandler; - scene.EventManager.OnSignificantClientMovement += SignificantClientMovementHandler; + scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; + scene.EventManager.OnNewClient += NewClientHandler; + scene.EventManager.OnSignificantClientMovement += SignificantClientMovementHandler; - LogoutRegionAgents(scene.RegionInfo.RegionID); + LogoutRegionAgents(scene.RegionInfo.RegionID); + } } public void RemoveRegion(Scene scene) { - scene.UnregisterModuleInterface(this); + if (!String.IsNullOrEmpty(m_serverUrl)) + { + scene.UnregisterModuleInterface(this); - scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; - scene.EventManager.OnNewClient -= NewClientHandler; - scene.EventManager.OnSignificantClientMovement -= SignificantClientMovementHandler; + scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; + scene.EventManager.OnNewClient -= NewClientHandler; + scene.EventManager.OnSignificantClientMovement -= SignificantClientMovementHandler; - LogoutRegionAgents(scene.RegionInfo.RegionID); + LogoutRegionAgents(scene.RegionInfo.RegionID); + } } #endregion ISharedRegionModule @@ -101,8 +107,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["PresenceService"]; if (gridConfig == null) { - m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini"); - throw new Exception("Presence connector init error"); + m_log.Info("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini, skipping SimianPresenceServiceConnector"); + return; } string serviceUrl = gridConfig.GetString("PresenceServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index 32f17ae..b3b171c 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -60,7 +60,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianProfiles + public class SimianProfiles : INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( @@ -69,15 +69,15 @@ namespace OpenSim.Services.Connectors.SimianGrid private string m_serverUrl = String.Empty; #region INonSharedRegionModule - + public Type ReplaceableInterface { get { return null; } } public void RegionLoaded(Scene scene) { } public void Close() { } public SimianProfiles() { } public string Name { get { return "SimianProfiles"; } } - public void AddRegion(Scene scene) { CheckEstateManager(scene); scene.EventManager.OnClientConnect += ClientConnectHandler; } - public void RemoveRegion(Scene scene) { scene.EventManager.OnClientConnect -= ClientConnectHandler; } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { CheckEstateManager(scene); scene.EventManager.OnClientConnect += ClientConnectHandler; } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.EventManager.OnClientConnect -= ClientConnectHandler; } } #endregion INonSharedRegionModule @@ -91,8 +91,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["UserAccountService"]; if (gridConfig == null) { - m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini"); - throw new Exception("Profiles init error"); + m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini, skipping SimianProfiles"); + return; } string serviceUrl = gridConfig.GetString("UserAccountServerURI"); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 708ced3..855b213 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -47,14 +47,14 @@ namespace OpenSim.Services.Connectors.SimianGrid /// users) to the SimianGrid backend /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianUserAccountServiceConnector : IUserAccountService + public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); private string m_serverUrl = String.Empty; - private ExpiringCache m_accountCache = new ExpiringCache(); + private ExpiringCache m_accountCache; #region ISharedRegionModule @@ -65,8 +65,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianUserAccountServiceConnector() { } public string Name { get { return "SimianUserAccountServiceConnector"; } } - public void AddRegion(Scene scene) { scene.RegisterModuleInterface(this); } - public void RemoveRegion(Scene scene) { scene.UnregisterModuleInterface(this); } + public void AddRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.RegisterModuleInterface(this); } } + public void RemoveRegion(Scene scene) { if (!String.IsNullOrEmpty(m_serverUrl)) { scene.UnregisterModuleInterface(this); } } #endregion ISharedRegionModule @@ -80,8 +80,8 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["UserAccountService"]; if (assetConfig == null) { - m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini"); - throw new Exception("User account connector init error"); + m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini, skipping SimianUserAccountServiceConnector"); + return; } string serviceURI = assetConfig.GetString("UserAccountServerURI"); @@ -91,6 +91,7 @@ namespace OpenSim.Services.Connectors.SimianGrid throw new Exception("User account connector init error"); } + m_accountCache = new ExpiringCache(); m_serverUrl = serviceURI; } -- cgit v1.1 From 9e3cdc4da5483ce0187c7774fa274e99845da232 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 12 Mar 2010 13:28:16 -0800 Subject: Fixing the previous patch to work correctly with standalone mode --- .../Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs | 8 ++++---- .../Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs | 8 ++++---- .../Connectors/SimianGrid/SimianAvatarServiceConnector.cs | 8 ++++---- .../Connectors/SimianGrid/SimianFriendsServiceConnector.cs | 8 ++++---- .../Services/Connectors/SimianGrid/SimianGridServiceConnector.cs | 8 ++++---- .../Connectors/SimianGrid/SimianInventoryServiceConnector.cs | 8 ++++---- .../Connectors/SimianGrid/SimianPresenceServiceConnector.cs | 8 ++++---- OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs | 8 ++++---- .../Connectors/SimianGrid/SimianUserAccountServiceConnector.cs | 8 ++++---- 9 files changed, 36 insertions(+), 36 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 89aa911..3f00534 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -88,15 +88,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["AssetService"]; if (gridConfig == null) { - m_log.Info("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini, skipping SimianAssetServiceConnector"); - return; + m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini"); + throw new Exception("Asset connector init error"); } string serviceUrl = gridConfig.GetString("AssetServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[ASSET CONNECTOR]: No AssetServerURI in section AssetService"); - throw new Exception("Asset connector init error"); + m_log.Info("[ASSET CONNECTOR]: No AssetServerURI in section AssetService, skipping SimianAssetServiceConnector"); + return; } if (!serviceUrl.EndsWith("/")) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 55aca36..0876efb 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -76,15 +76,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["AuthenticationService"]; if (assetConfig == null) { - m_log.Info("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini, skipping SimianAuthenticationServiceConnector"); - return; + m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini"); + throw new Exception("Authentication connector init error"); } string serviceURI = assetConfig.GetString("AuthenticationServerURI"); if (String.IsNullOrEmpty(serviceURI)) { - m_log.Error("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService"); - throw new Exception("Authentication connector init error"); + m_log.Info("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService, skipping SimianAuthenticationServiceConnector"); + return; } m_serverUrl = serviceURI; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index b5cef0c..697bb43 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -81,15 +81,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["AvatarService"]; if (gridConfig == null) { - m_log.Info("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini, skipping SimianAvatarServiceConnector"); - return; + m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini"); + throw new Exception("Avatar connector init error"); } string serviceUrl = gridConfig.GetString("AvatarServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[AVATAR CONNECTOR]: No AvatarServerURI in section AvatarService"); - throw new Exception("Avatar connector init error"); + m_log.Info("[AVATAR CONNECTOR]: No AvatarServerURI in section AvatarService, skipping SimianAvatarServiceConnector"); + return; } if (!serviceUrl.EndsWith("/")) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index a569e91..abb98a3 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -79,15 +79,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["FriendsService"]; if (assetConfig == null) { - m_log.Info("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini, skipping SimianFriendsServiceConnector"); - return; + m_log.Error("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini"); + throw new Exception("Friends connector init error"); } string serviceURI = assetConfig.GetString("FriendsServerURI"); if (String.IsNullOrEmpty(serviceURI)) { - m_log.Error("[FRIENDS CONNECTOR]: No Server URI named in section FriendsService"); - throw new Exception("Friends connector init error"); + m_log.Info("[FRIENDS CONNECTOR]: No Server URI named in section FriendsService, skipping SimianFriendsServiceConnector"); + return; } m_serverUrl = serviceURI; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 2e600f0..ef943ec 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -83,15 +83,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["GridService"]; if (gridConfig == null) { - m_log.Info("[GRID CONNECTOR]: GridService missing from OpenSim.ini, skipping SimianGridServiceConnector"); - return; + m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); + throw new Exception("Grid connector init error"); } string serviceUrl = gridConfig.GetString("GridServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[GRID CONNECTOR]: No Server URI named in section GridService"); - throw new Exception("Grid connector init error"); + m_log.Info("[GRID CONNECTOR]: No Server URI named in section GridService, skipping SimianGridServiceConnector"); + return; } m_serverUrl = serviceUrl; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index a50ecbc..a41e493 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -95,15 +95,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["InventoryService"]; if (gridConfig == null) { - m_log.Info("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini, skipping SimianInventoryServiceConnector"); - return; + m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); + throw new Exception("Inventory connector init error"); } string serviceUrl = gridConfig.GetString("InventoryServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService"); - throw new Exception("Inventory connector init error"); + m_log.Info("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService, skipping SimianInventoryServiceConnector"); + return; } // FIXME: Get the user server URL too diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 542093f..fa387ba 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -107,15 +107,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["PresenceService"]; if (gridConfig == null) { - m_log.Info("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini, skipping SimianPresenceServiceConnector"); - return; + m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini"); + throw new Exception("Presence connector init error"); } string serviceUrl = gridConfig.GetString("PresenceServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[PRESENCE CONNECTOR]: No PresenceServerURI in section PresenceService"); - throw new Exception("Presence connector init error"); + m_log.Info("[PRESENCE CONNECTOR]: No PresenceServerURI in section PresenceService, skipping SimianPresenceServiceConnector"); + return; } m_serverUrl = serviceUrl; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index b3b171c..3c93725 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -91,15 +91,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig gridConfig = source.Configs["UserAccountService"]; if (gridConfig == null) { - m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini, skipping SimianProfiles"); - return; + m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini"); + throw new Exception("Profiles init error"); } string serviceUrl = gridConfig.GetString("UserAccountServerURI"); if (String.IsNullOrEmpty(serviceUrl)) { - m_log.Error("[PROFILES]: No UserAccountServerURI in section UserAccountService"); - throw new Exception("Profiles init error"); + m_log.Info("[PROFILES]: No UserAccountServerURI in section UserAccountService, skipping SimianProfiles"); + return; } if (!serviceUrl.EndsWith("/")) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 855b213..3a35d9a 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -80,15 +80,15 @@ namespace OpenSim.Services.Connectors.SimianGrid IConfig assetConfig = source.Configs["UserAccountService"]; if (assetConfig == null) { - m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini, skipping SimianUserAccountServiceConnector"); - return; + m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini"); + throw new Exception("User account connector init error"); } string serviceURI = assetConfig.GetString("UserAccountServerURI"); if (String.IsNullOrEmpty(serviceURI)) { - m_log.Error("[ACCOUNT CONNECTOR]: No UserAccountServerURI in section UserAccountService"); - throw new Exception("User account connector init error"); + m_log.Info("[ACCOUNT CONNECTOR]: No UserAccountServerURI in section UserAccountService, skipping SimianUserAccountServiceConnector"); + return; } m_accountCache = new ExpiringCache(); -- cgit v1.1 From 19b4770fe7620b184060b57fe5fa4418c5010c14 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 22:18:48 +0000 Subject: start laoding griduser local connector, though it isn't invoked by anything yet --- OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 0195c03..aaa318c 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -56,6 +56,9 @@ + + + -- cgit v1.1 From 3036aba875187923b4e4d8481d46334e53393107 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 12 Mar 2010 14:28:31 -0800 Subject: * Added a better check to the SimianGrid connectors to test if they are enabled or not. This method should work equally well with standalone or robust mode * Applying #4602 from Misterblu to add collision detection to BulletDotNET --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 + .../BulletDotNETPlugin/BulletDotNETCharacter.cs | 33 ++++++- .../Physics/BulletDotNETPlugin/BulletDotNETPrim.cs | 102 +++++++++++++++------ .../BulletDotNETPlugin/BulletDotNETScene.cs | 99 +++++++++++++++++--- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 4 +- .../SimianGrid/SimianAssetServiceConnector.cs | 31 ++++--- .../SimianAuthenticationServiceConnector.cs | 27 +++--- .../SimianGrid/SimianAvatarServiceConnector.cs | 31 ++++--- .../SimianGrid/SimianFriendsServiceConnector.cs | 27 +++--- .../Services/Connectors/SimianGrid/SimianGrid.cs | 16 ++++ .../SimianGrid/SimianGridServiceConnector.cs | 27 +++--- .../SimianGrid/SimianInventoryServiceConnector.cs | 41 ++++++--- .../SimianGrid/SimianPresenceServiceConnector.cs | 27 +++--- .../Connectors/SimianGrid/SimianProfiles.cs | 31 ++++--- .../SimianUserAccountServiceConnector.cs | 29 +++--- 15 files changed, 363 insertions(+), 163 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 8967252..a2b98b9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2044,6 +2044,7 @@ namespace OpenSim.Region.Framework.Scenes { m_lastColliders.Remove(localID); } + if (m_parentGroup == null) return; if (m_parentGroup.IsDeleted) diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs index 6a54705..ac4e2b9 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs @@ -108,12 +108,11 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin private bool[] m_colliderarr = new bool[11]; private bool[] m_colliderGroundarr = new bool[11]; - - private BulletDotNETScene m_parent_scene; public int m_eventsubscription = 0; - // private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); + private CollisionEventUpdate CollisionEventsThisFrame = null; + private int m_requestedUpdateFrequency = 0; public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) { @@ -212,7 +211,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin m_mass = Mass; Body = new btRigidBody(m_mass, m_bodyMotionState, Shell); - Body.setUserPointer(new IntPtr((int)Body.Handle)); + // this is used for self identification. User localID instead of body handle + Body.setUserPointer(new IntPtr((int)m_localID)); if (ClosestCastResult != null) ClosestCastResult.Dispose(); @@ -717,6 +717,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin public override void SubscribeEvents(int ms) { m_eventsubscription = ms; + m_requestedUpdateFrequency = ms; m_parent_scene.addCollisionEventReporting(this); } @@ -724,6 +725,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { m_parent_scene.remCollisionEventReporting(this); m_eventsubscription = 0; + m_requestedUpdateFrequency = 0; } public override bool SubscribedEvents() @@ -733,6 +735,29 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin return false; } + public void AddCollision(uint collideWith, ContactPoint contact) + { + if (CollisionEventsThisFrame == null) + { + CollisionEventsThisFrame = new CollisionEventUpdate(); + } + CollisionEventsThisFrame.addCollider(collideWith, contact); + } + + public void SendCollisions() + { + if (m_eventsubscription >= m_requestedUpdateFrequency) + { + if (CollisionEventsThisFrame != null) + { + base.SendCollisionUpdate(CollisionEventsThisFrame); + } + CollisionEventsThisFrame = new CollisionEventUpdate(); + m_eventsubscription = 0; + } + return; + } + internal void Dispose() { if (Body.isInWorld()) diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs index 920ed96..dc3229a 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs @@ -154,7 +154,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin private Vector3 _target_velocity; public int m_eventsubscription; - // private CollisionEventUpdate CollisionEventsThisFrame = null; + private int m_requestedUpdateFrequency = 0; + private CollisionEventUpdate CollisionEventsThisFrame = null; public volatile bool childPrim; @@ -595,6 +596,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin public override void SubscribeEvents(int ms) { m_eventsubscription = ms; + m_requestedUpdateFrequency = ms; _parent_scene.addCollisionEventReporting(this); } @@ -602,6 +604,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { _parent_scene.remCollisionEventReporting(this); m_eventsubscription = 0; + m_requestedUpdateFrequency = 0; } public override bool SubscribedEvents() @@ -611,7 +614,28 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin #endregion + public void AddCollision(uint collideWith, ContactPoint contact) + { + if (CollisionEventsThisFrame == null) + { + CollisionEventsThisFrame = new CollisionEventUpdate(); + } + CollisionEventsThisFrame.addCollider(collideWith, contact); + } + public void SendCollisions() + { + if (m_eventsubscription >= m_requestedUpdateFrequency) + { + if (CollisionEventsThisFrame != null) + { + base.SendCollisionUpdate(CollisionEventsThisFrame); + } + CollisionEventsThisFrame = null; + // m_eventsubscription = 0; + } + return; + } internal void Dispose() { @@ -759,7 +783,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (m_taintadd) { - m_log.Debug("[PHYSICS]: TaintAdd"); + // m_log.Debug("[PHYSICS]: TaintAdd"); changeadd(timestep); } @@ -771,7 +795,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin SetBody(Mass); else SetBody(0); - m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT"); + // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT"); } if (prim_geom.Handle == IntPtr.Zero) @@ -782,31 +806,31 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin SetBody(Mass); else SetBody(0); - m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT"); + // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT"); } if (!_position.ApproxEquals(m_taintposition, 0f)) { - m_log.Debug("[PHYSICS]: TaintMove"); + // m_log.Debug("[PHYSICS]: TaintMove"); changemove(timestep); } if (m_taintrot != _orientation) { - m_log.Debug("[PHYSICS]: TaintRotate"); + // m_log.Debug("[PHYSICS]: TaintRotate"); rotate(timestep); } // if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) { - m_log.Debug("[PHYSICS]: TaintPhysics"); + // m_log.Debug("[PHYSICS]: TaintPhysics"); changePhysicsStatus(timestep); } // if (!_size.ApproxEquals(m_taintsize, 0f)) { - m_log.Debug("[PHYSICS]: TaintSize"); + // m_log.Debug("[PHYSICS]: TaintSize"); changesize(timestep); } @@ -814,43 +838,43 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin if (m_taintshape) { - m_log.Debug("[PHYSICS]: TaintShape"); + // m_log.Debug("[PHYSICS]: TaintShape"); changeshape(timestep); } // if (m_taintforce) { - m_log.Debug("[PHYSICS]: TaintForce"); + // m_log.Debug("[PHYSICS]: TaintForce"); changeAddForce(timestep); } if (m_taintaddangularforce) { - m_log.Debug("[PHYSICS]: TaintAngularForce"); + // m_log.Debug("[PHYSICS]: TaintAngularForce"); changeAddAngularForce(timestep); } if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) { - m_log.Debug("[PHYSICS]: TaintTorque"); + // m_log.Debug("[PHYSICS]: TaintTorque"); changeSetTorque(timestep); } if (m_taintdisable) { - m_log.Debug("[PHYSICS]: TaintDisable"); + // m_log.Debug("[PHYSICS]: TaintDisable"); changedisable(timestep); } if (m_taintselected != m_isSelected) { - m_log.Debug("[PHYSICS]: TaintSelected"); + // m_log.Debug("[PHYSICS]: TaintSelected"); changeSelectedStatus(timestep); } if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) { - m_log.Debug("[PHYSICS]: TaintVelocity"); + // m_log.Debug("[PHYSICS]: TaintVelocity"); changevelocity(timestep); } if (m_taintparent != _parent) { - m_log.Debug("[PHYSICS]: TaintLink"); + // m_log.Debug("[PHYSICS]: TaintLink"); changelink(timestep); } if (m_taintCollidesWater != m_collidesWater) @@ -859,7 +883,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } if (!m_angularlock.ApproxEquals(m_taintAngularLock, 0)) { - m_log.Debug("[PHYSICS]: TaintAngularLock"); + // m_log.Debug("[PHYSICS]: TaintAngularLock"); changeAngularLock(timestep); } if (m_taintremove) @@ -917,7 +941,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin private void changemove(float timestep) { - m_log.Debug("[PHYSICS]: _________ChangeMove"); + // m_log.Debug("[PHYSICS]: _________ChangeMove"); if (!m_isphysical) { tempTransform2 = Body.getWorldTransform(); @@ -977,7 +1001,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin private void rotate(float timestep) { - m_log.Debug("[PHYSICS]: _________ChangeRotate"); + // m_log.Debug("[PHYSICS]: _________ChangeRotate"); tempTransform2 = Body.getWorldTransform(); tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W); tempTransform2.setRotation(tempOrientation2); @@ -1000,7 +1024,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin //Body = null; // TODO: dispose parts that make up body } - m_log.Debug("[PHYSICS]: _________ChangePhysics"); + // m_log.Debug("[PHYSICS]: _________ChangePhysics"); ProcessGeomCreation(); @@ -1092,7 +1116,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // TODO: dispose parts that make up body } - m_log.Debug("[PHYSICS]: _________ChangeSize"); + // m_log.Debug("[PHYSICS]: _________ChangeSize"); SetCollisionShape(null); // Construction of new prim ProcessGeomCreation(); @@ -1297,13 +1321,13 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // TODO: throw new NotImplementedException(); if (m_taintselected) { - Body.setCollisionFlags((int)ContactFlags.CF_NO_CONTACT_RESPONSE); + // Body.setCollisionFlags((int)ContactFlags.CF_NO_CONTACT_RESPONSE); disableBodySoft(); } else { - Body.setCollisionFlags(0 | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK); + // Body.setCollisionFlags(0 | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK); enableBodySoft(); } m_isSelected = m_taintselected; @@ -1605,6 +1629,11 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin enableBodySoft(); } */ + if (!Body.isActive()) + { + Body.clearForces(); + enableBodySoft(); + } // 35x10 = 350n times the mass per second applied maximum. float nmax = 35f * m_mass; @@ -1632,6 +1661,12 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin Body.applyCentralImpulse(tempAddForce); } } + else + { + // if no forces on the prim, make sure everything is zero + Body.clearForces(); + enableBodySoft(); + } } else { @@ -1985,7 +2020,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin public void CreateGeom(IntPtr m_targetSpace, IMesh p_mesh) { - m_log.Debug("[PHYSICS]: _________CreateGeom"); + // m_log.Debug("[PHYSICS]: _________CreateGeom"); if (p_mesh != null) { //_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); @@ -2042,7 +2077,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // TODO: Set Collision Body Mesh // This sleeper is there to moderate how long it takes between // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object - m_log.Debug("_________SetMesh"); + // m_log.Debug("_________SetMesh"); Thread.Sleep(10); //Kill Body so that mesh can re-make the geom @@ -2159,7 +2194,14 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // Body = new btRigidBody(mass, tempMotionState1, prim_geom); //else - Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + if (Body == null) + { + Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + // add localID so we can later map bullet object back to OpenSim object + Body.setUserPointer(new IntPtr((int)m_localID)); + } + if (prim_geom is btGImpactMeshShape) { @@ -2250,7 +2292,13 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // Body = new btRigidBody(mass, tempMotionState1, prim_geom); //else - Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + if (Body == null) + { + Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1); + // each body has the localID stored into it so we can identify collision objects + Body.setUserPointer(new IntPtr((int)m_localID)); + } if (prim_geom is btGImpactMeshShape) { diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs index 9e048ab..85e34c1 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs @@ -47,7 +47,9 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin // private string m_sceneIdentifier = string.Empty; private List m_characters = new List(); + private Dictionary m_charactersLocalID = new Dictionary(); private List m_prims = new List(); + private Dictionary m_primsLocalID = new Dictionary(); private List m_activePrims = new List(); private List m_taintedActors = new List(); private btDiscreteDynamicsWorld m_world; @@ -134,7 +136,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); m_world.setGravity(m_gravity); - //EnableCollisionInterface(); + EnableCollisionInterface(); } @@ -145,7 +147,16 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun); - m_characters.Add(chr); + try + { + m_characters.Add(chr); + m_charactersLocalID.Add(chr.m_localID, chr); + } + catch + { + // noop if it's already there + m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate avatar localID"); + } AddPhysicsActorTaint(chr); return chr; } @@ -154,6 +165,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { BulletDotNETCharacter chr = (BulletDotNETCharacter) actor; + m_charactersLocalID.Remove(chr.m_localID); m_characters.Remove(chr); m_world.removeRigidBody(chr.Body); m_world.removeCollisionObject(chr.Body); @@ -279,7 +291,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin prim.Move(timeStep); } } - float steps = m_world.stepSimulation(timeStep * 1000, 10, WorldTimeComp); + float steps = m_world.stepSimulation(timeStep, 10, WorldTimeComp); foreach (BulletDotNETCharacter chr in m_characters) { @@ -296,20 +308,67 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } if (m_CollisionInterface != null) { - List collisions = m_CollisionInterface.GetContactList(); - lock (collisions) + List primsWithCollisions = new List(); + List charactersWithCollisions = new List(); + + // get the collisions that happened this tick + List collisions = m_CollisionInterface.GetContactList(); + // passed back the localID of the prim so we can associate the prim + foreach (BulletDotNET.ContactAddedCallbackHandler.ContactInfo ci in collisions) { - foreach (int pvalue in collisions) - { - System.Console.Write(string.Format("{0} ", pvalue)); - } + // ContactPoint = { contactPoint, contactNormal, penetrationDepth } + ContactPoint contact = new ContactPoint(new Vector3(ci.pX, ci.pY, ci.pZ), + new Vector3(ci.nX, ci.nY, ci.nZ), ci.depth); + + ProcessContact(ci.contact, ci.contactWith, contact, ref primsWithCollisions, ref charactersWithCollisions); + ProcessContact(ci.contactWith, ci.contact, contact, ref primsWithCollisions, ref charactersWithCollisions); + } m_CollisionInterface.Clear(); - + // for those prims and characters that had collisions cause collision events + foreach (BulletDotNETPrim bdnp in primsWithCollisions) + { + bdnp.SendCollisions(); + } + foreach (BulletDotNETCharacter bdnc in charactersWithCollisions) + { + bdnc.SendCollisions(); + } } return steps; } + private void ProcessContact(uint cont, uint contWith, ContactPoint contact, + ref List primsWithCollisions, + ref List charactersWithCollisions) + { + BulletDotNETPrim bdnp; + // collisions with a normal prim? + if (m_primsLocalID.TryGetValue(cont, out bdnp)) + { + // Added collision event to the prim. This creates a pile of events + // that will be sent to any subscribed listeners. + bdnp.AddCollision(contWith, contact); + if (!primsWithCollisions.Contains(bdnp)) + { + primsWithCollisions.Add(bdnp); + } + } + else + { + BulletDotNETCharacter bdnc; + // if not a prim, maybe it's one of the characters + if (m_charactersLocalID.TryGetValue(cont, out bdnc)) + { + bdnc.AddCollision(contWith, contact); + if (!charactersWithCollisions.Contains(bdnc)) + { + charactersWithCollisions.Add(bdnc); + } + } + } + } + public override void GetResults() { @@ -387,6 +446,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition); m_terrainMotionState = new btDefaultMotionState(m_terrainTransform); TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape); + TerrainBody.setUserPointer((IntPtr)0); m_world.addRigidBody(TerrainBody); @@ -459,6 +519,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { lock (m_prims) { + m_primsLocalID.Clear(); foreach (BulletDotNETPrim prim in m_prims) { if (prim.Body != null) @@ -513,6 +574,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin m_world.removeRigidBody(body); } remActivePrim(prm); + m_primsLocalID.Remove(prm.m_localID); m_prims.Remove(prm); } @@ -686,9 +748,18 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (!m_prims.Contains(pPrim)) { - m_prims.Add(pPrim); + try + { + m_prims.Add(pPrim); + m_primsLocalID.Add(pPrim.m_localID, pPrim); + } + catch + { + // noop if it's already there + m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID"); + } m_world.addRigidBody(pPrim.Body); - m_log.Debug("ADDED"); + // m_log.Debug("[PHYSICS] added prim to scene"); } } } @@ -696,8 +767,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (m_CollisionInterface == null) { - m_CollisionInterface = new ContactAddedCallbackHandler(); - m_world.SetCollisionAddedCallback(m_CollisionInterface); + m_CollisionInterface = new ContactAddedCallbackHandler(m_world); + // m_world.SetCollisionAddedCallback(m_CollisionInterface); } } diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 03736d1..0720b5e 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1575,11 +1575,11 @@ Console.WriteLine(" JointCreateFixed"); { //Console.WriteLine("Move " + m_primName); if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 - /* // NON-'VEHICLES' are dealt with here if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) { d.Vector3 avel2 = d.BodyGetAngularVel(Body); + /* if (m_angularlock.X == 1) avel2.X = 0; if (m_angularlock.Y == 1) @@ -1587,8 +1587,8 @@ Console.WriteLine(" JointCreateFixed"); if (m_angularlock.Z == 1) avel2.Z = 0; d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); + */ } - */ //float PID_P = 900.0f; float m_mass = CalculateMass(); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 3f00534..7cb075e 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -85,24 +85,27 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["AssetService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "AssetServices")) { - m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini"); - throw new Exception("Asset connector init error"); - } + IConfig gridConfig = source.Configs["AssetService"]; + if (gridConfig == null) + { + m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini"); + throw new Exception("Asset connector init error"); + } - string serviceUrl = gridConfig.GetString("AssetServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[ASSET CONNECTOR]: No AssetServerURI in section AssetService, skipping SimianAssetServiceConnector"); - return; - } + string serviceUrl = gridConfig.GetString("AssetServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[ASSET CONNECTOR]: No AssetServerURI in section AssetService"); + throw new Exception("Asset connector init error"); + } - if (!serviceUrl.EndsWith("/")) - serviceUrl = serviceUrl + '/'; + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; + m_serverUrl = serviceUrl; + } } #region IAssetService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 0876efb..6317b87 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -73,21 +73,24 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig assetConfig = source.Configs["AuthenticationService"]; - if (assetConfig == null) + if (Simian.IsSimianEnabled(source, "AuthenticationServices")) { - m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini"); - throw new Exception("Authentication connector init error"); - } + IConfig assetConfig = source.Configs["AuthenticationService"]; + if (assetConfig == null) + { + m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini"); + throw new Exception("Authentication connector init error"); + } - string serviceURI = assetConfig.GetString("AuthenticationServerURI"); - if (String.IsNullOrEmpty(serviceURI)) - { - m_log.Info("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService, skipping SimianAuthenticationServiceConnector"); - return; - } + string serviceURI = assetConfig.GetString("AuthenticationServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService"); + throw new Exception("Authentication connector init error"); + } - m_serverUrl = serviceURI; + m_serverUrl = serviceURI; + } } public string Authenticate(UUID principalID, string password, int lifetime) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 697bb43..a18cb22 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -78,24 +78,27 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["AvatarService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "AvatarServices")) { - m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini"); - throw new Exception("Avatar connector init error"); - } + IConfig gridConfig = source.Configs["AvatarService"]; + if (gridConfig == null) + { + m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini"); + throw new Exception("Avatar connector init error"); + } - string serviceUrl = gridConfig.GetString("AvatarServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[AVATAR CONNECTOR]: No AvatarServerURI in section AvatarService, skipping SimianAvatarServiceConnector"); - return; - } + string serviceUrl = gridConfig.GetString("AvatarServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[AVATAR CONNECTOR]: No AvatarServerURI in section AvatarService"); + throw new Exception("Avatar connector init error"); + } - if (!serviceUrl.EndsWith("/")) - serviceUrl = serviceUrl + '/'; + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; + m_serverUrl = serviceUrl; + } } #region IAvatarService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index abb98a3..b3ecc7e 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -76,21 +76,24 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig assetConfig = source.Configs["FriendsService"]; - if (assetConfig == null) + if (Simian.IsSimianEnabled(source, "FriendsServices")) { - m_log.Error("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini"); - throw new Exception("Friends connector init error"); - } + IConfig assetConfig = source.Configs["FriendsService"]; + if (assetConfig == null) + { + m_log.Error("[FRIENDS CONNECTOR]: FriendsService missing from OpenSim.ini"); + throw new Exception("Friends connector init error"); + } - string serviceURI = assetConfig.GetString("FriendsServerURI"); - if (String.IsNullOrEmpty(serviceURI)) - { - m_log.Info("[FRIENDS CONNECTOR]: No Server URI named in section FriendsService, skipping SimianFriendsServiceConnector"); - return; - } + string serviceURI = assetConfig.GetString("FriendsServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[FRIENDS CONNECTOR]: No Server URI named in section FriendsService"); + throw new Exception("Friends connector init error"); + } - m_serverUrl = serviceURI; + m_serverUrl = serviceURI; + } } #region IFriendsService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs index 41ed2f1..c3de98e 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs @@ -25,7 +25,23 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using Mono.Addins; +using Nini.Config; [assembly: Addin("SimianGrid", "1.0")] [assembly: AddinDependency("OpenSim", "0.5")] + +public static class Simian +{ + public static bool IsSimianEnabled(IConfigSource config, string moduleName) + { + if (config.Configs["Modules"] != null) + { + string module = config.Configs["Modules"].GetString("AuthenticationServices"); + return !String.IsNullOrEmpty(module) && module.Contains("Simian"); + } + + return false; + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index ef943ec..eebdf14 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -80,21 +80,24 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["GridService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "GridServices")) { - m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); - throw new Exception("Grid connector init error"); - } + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig == null) + { + m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); + throw new Exception("Grid connector init error"); + } - string serviceUrl = gridConfig.GetString("GridServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[GRID CONNECTOR]: No Server URI named in section GridService, skipping SimianGridServiceConnector"); - return; - } + string serviceUrl = gridConfig.GetString("GridServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[GRID CONNECTOR]: No Server URI named in section GridService"); + throw new Exception("Grid connector init error"); + } - m_serverUrl = serviceUrl; + m_serverUrl = serviceUrl; + } } #region IGridService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index a41e493..891782f 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -92,23 +92,38 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["InventoryService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "InventoryServices")) { - m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); - throw new Exception("Inventory connector init error"); - } + IConfig gridConfig = source.Configs["InventoryService"]; + if (gridConfig == null) + { + m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); + throw new Exception("Inventory connector init error"); + } - string serviceUrl = gridConfig.GetString("InventoryServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService, skipping SimianInventoryServiceConnector"); - return; - } + string serviceUrl = gridConfig.GetString("InventoryServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService"); + throw new Exception("Inventory connector init error"); + } - // FIXME: Get the user server URL too + m_serverUrl = serviceUrl; - m_serverUrl = serviceUrl; + gridConfig = source.Configs["UserAccountService"]; + if (gridConfig != null) + { + serviceUrl = gridConfig.GetString("UserAccountServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + m_userServerUrl = serviceUrl; + else + m_log.Info("[INVENTORY CONNECTOR]: No Server URI named in section UserAccountService"); + } + else + { + m_log.Warn("[INVENTORY CONNECTOR]: UserAccountService missing from OpenSim.ini"); + } + } } /// diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index fa387ba..1b5edf4 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -104,21 +104,24 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["PresenceService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "PresenceServices")) { - m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini"); - throw new Exception("Presence connector init error"); - } + IConfig gridConfig = source.Configs["PresenceService"]; + if (gridConfig == null) + { + m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini"); + throw new Exception("Presence connector init error"); + } - string serviceUrl = gridConfig.GetString("PresenceServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[PRESENCE CONNECTOR]: No PresenceServerURI in section PresenceService, skipping SimianPresenceServiceConnector"); - return; - } + string serviceUrl = gridConfig.GetString("PresenceServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[PRESENCE CONNECTOR]: No PresenceServerURI in section PresenceService"); + throw new Exception("Presence connector init error"); + } - m_serverUrl = serviceUrl; + m_serverUrl = serviceUrl; + } } #region IPresenceService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index 3c93725..9c226fb 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -88,24 +88,27 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig gridConfig = source.Configs["UserAccountService"]; - if (gridConfig == null) + if (Simian.IsSimianEnabled(source, "UserAccountServices")) { - m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini"); - throw new Exception("Profiles init error"); - } + IConfig gridConfig = source.Configs["UserAccountService"]; + if (gridConfig == null) + { + m_log.Error("[PROFILES]: UserAccountService missing from OpenSim.ini"); + throw new Exception("Profiles init error"); + } - string serviceUrl = gridConfig.GetString("UserAccountServerURI"); - if (String.IsNullOrEmpty(serviceUrl)) - { - m_log.Info("[PROFILES]: No UserAccountServerURI in section UserAccountService, skipping SimianProfiles"); - return; - } + string serviceUrl = gridConfig.GetString("UserAccountServerURI"); + if (String.IsNullOrEmpty(serviceUrl)) + { + m_log.Error("[PROFILES]: No UserAccountServerURI in section UserAccountService"); + throw new Exception("Profiles init error"); + } - if (!serviceUrl.EndsWith("/")) - serviceUrl = serviceUrl + '/'; + if (!serviceUrl.EndsWith("/")) + serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; + m_serverUrl = serviceUrl; + } } private void ClientConnectHandler(IClientCore clientCore) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 3a35d9a..bb0ac57 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -77,22 +77,25 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - IConfig assetConfig = source.Configs["UserAccountService"]; - if (assetConfig == null) + if (Simian.IsSimianEnabled(source, "UserAccountServices")) { - m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini"); - throw new Exception("User account connector init error"); - } + IConfig assetConfig = source.Configs["UserAccountService"]; + if (assetConfig == null) + { + m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini"); + throw new Exception("User account connector init error"); + } - string serviceURI = assetConfig.GetString("UserAccountServerURI"); - if (String.IsNullOrEmpty(serviceURI)) - { - m_log.Info("[ACCOUNT CONNECTOR]: No UserAccountServerURI in section UserAccountService, skipping SimianUserAccountServiceConnector"); - return; - } + string serviceURI = assetConfig.GetString("UserAccountServerURI"); + if (String.IsNullOrEmpty(serviceURI)) + { + m_log.Error("[ACCOUNT CONNECTOR]: No UserAccountServerURI in section UserAccountService, skipping SimianUserAccountServiceConnector"); + throw new Exception("User account connector init error"); + } - m_accountCache = new ExpiringCache(); - m_serverUrl = serviceURI; + m_accountCache = new ExpiringCache(); + m_serverUrl = serviceURI; + } } public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) -- cgit v1.1 From b9f5cd75bc9b46b067d151a1a13d4e95cc98cedb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 22:39:15 +0000 Subject: refactor: move client invoked AttachObject from SceneGraph to AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 32 +++++++++++++++++++- .../Framework/Interfaces/IAttachmentsModule.cs | 17 +++++++++-- OpenSim/Region/Framework/Scenes/Scene.cs | 13 ++++---- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 35 ---------------------- 4 files changed, 53 insertions(+), 44 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 3b7fe88..3c2cc42 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -67,6 +67,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments get { return false; } } + public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) + { + m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject"); + + // If we can't take it, we can't attach it! + SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID); + if (part == null) + return; + + if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) + return; + + // Calls attach with a Zero position + if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) + { + m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); + + // Save avatar attachment information + ScenePresence presence; + if (m_scene.AvatarFactory != null && m_scene.TryGetAvatar(remoteClient.AgentId, out presence)) + { + m_log.Info( + "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + + ", AttachmentPoint: " + AttachmentPt); + + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } + } + } + public bool AttachObject( IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) { @@ -143,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { m_log.DebugFormat( - "[ATTACHMENTS MODULEY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", + "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} (item ID {2})", remoteClient.Name, att.Name, itemID); if (!att.IsDeleted) diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 6cf2a2e..21c1056 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -35,17 +35,28 @@ namespace OpenSim.Region.Framework.Interfaces public interface IAttachmentsModule { /// + /// Attach an object to an avatar from the world. + /// + /// + /// + /// + /// + /// + void AttachObject( + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent); + + /// /// Attach an object to an avatar. /// /// /// /// /// - /// + /// /// - /// true if the object was successfully attached, false otherwise + /// true if the object was successfully attached, false otherwise bool AttachObject( - IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); /// /// Update the user inventory to the attachment of an item diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 87a753e..d4d134f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2644,12 +2644,14 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) { client.OnRezSingleAttachmentFromInv += RezSingleAttachment; - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; - client.OnObjectAttach += m_sceneGraph.AttachObject; + client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; client.OnObjectDetach += m_sceneGraph.DetachObject; if (AttachmentsModule != null) + { + client.OnObjectAttach += AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; + } } public virtual void SubscribeToClientTeleportEvents(IClientAPI client) @@ -2774,7 +2776,6 @@ namespace OpenSim.Region.Framework.Scenes client.OnRezObject -= RezObject; } - public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) { client.OnCreateNewInventoryItem -= CreateNewInventoryItem; @@ -2799,12 +2800,14 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) { client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; - client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; - client.OnObjectAttach -= m_sceneGraph.AttachObject; + client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; client.OnObjectDetach -= m_sceneGraph.DetachObject; if (AttachmentsModule != null) + { + client.OnObjectAttach -= AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; + } } public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 380722d..a88d456 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -487,41 +487,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Event Handling routine for Attach Object - /// - /// - /// - /// - /// - protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) - { - // If we can't take it, we can't attach it! - SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID); - if (part == null) - return; - - if (!m_parentScene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) - return; - - // Calls attach with a Zero position - if (m_parentScene.AttachmentsModule.AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) - { - m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); - - // Save avatar attachment information - ScenePresence presence; - if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence)) - { - m_log.Info( - "[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId - + ", AttachmentPoint: " + AttachmentPt); - - m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } - } - - /// /// Rez an attachment /// /// -- cgit v1.1 From 3ea9fdea8b8a17f50e2156e7a09ebb6523a0d4fc Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 12 Mar 2010 14:39:51 -0800 Subject: Minor tweak to clean up SimianGrid asset service URLs --- OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 7cb075e..1c22a72 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -101,7 +101,7 @@ namespace OpenSim.Services.Connectors.SimianGrid throw new Exception("Asset connector init error"); } - if (!serviceUrl.EndsWith("/")) + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) serviceUrl = serviceUrl + '/'; m_serverUrl = serviceUrl; -- cgit v1.1 From 582375509c82220c40579c4e4095225bd9d67010 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 22:48:49 +0000 Subject: refactor: move RezSingleAttachmentFromInventory() from SceneGraph to AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 46 +++++++++++++++++++ .../Framework/Interfaces/IAttachmentsModule.cs | 11 ++++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 53 ---------------------- 5 files changed, 60 insertions(+), 58 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 3c2cc42..084f3c9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -168,6 +168,52 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } + + public SceneObjectGroup RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + { + IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); + if (invAccess != null) + { + SceneObjectGroup objatt = invAccess.RezObject(remoteClient, + itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + false, false, remoteClient.AgentId, true); + +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", +// objatt.Name, remoteClient.Name, AttachmentPt); + + if (objatt != null) + { + bool tainted = false; + if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) + tainted = true; + + AttachObject( + remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); + //objatt.ScheduleGroupForFullUpdate(); + + if (tainted) + objatt.HasGroupChanged = true; + + // Fire after attach, so we don't get messy perms dialogs + // 3 == AttachedRez + objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); + + // Do this last so that event listeners have access to all the effects of the attachment + m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); + } + else + { + m_log.WarnFormat( + "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", + itemID, remoteClient.Name, AttachmentPt); + } + + return objatt; + } + + return null; + } public UUID SetAttachmentInventoryStatus( SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 21c1056..1fa77e4 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -56,7 +56,16 @@ namespace OpenSim.Region.Framework.Interfaces /// /// true if the object was successfully attached, false otherwise bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); + + /// + /// Rez an attachment from user inventory + /// + /// + /// + /// + /// The scene object that was attached. Null if the scene object could not be found + SceneObjectGroup RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); /// /// Update the user inventory to the attachment of an item diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7277527..dcd92d6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1854,7 +1854,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.DebugFormat("[USER INVENTORY]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); - SceneObjectGroup att = m_sceneGraph.RezSingleAttachment(remoteClient, itemID, AttachmentPt); + SceneObjectGroup att = AttachmentsModule.RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt); if (att == null) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d4d134f..50553dd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2338,10 +2338,10 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); ScenePresence sp = GetScenePresence(userID); - if (sp != null) + if (sp != null && AttachmentsModule != null) { - uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); - m_sceneGraph.RezSingleAttachment(sp.ControllingClient, itemID, attPt); + uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); + AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); } return false; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a88d456..d944834 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -486,59 +486,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Rez an attachment - /// - /// - /// - /// - /// The scene object that was attached. Null if the scene object could not be found - public SceneObjectGroup RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) - { - IInventoryAccessModule invAccess = m_parentScene.RequestModuleInterface(); - if (invAccess != null) - { - SceneObjectGroup objatt = invAccess.RezObject(remoteClient, - itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, - false, false, remoteClient.AgentId, true); - -// m_log.DebugFormat( -// "[SCENE GRAPH]: Retrieved single object {0} for attachment to {1} on point {2}", -// objatt.Name, remoteClient.Name, AttachmentPt); - - if (objatt != null) - { - bool tainted = false; - if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) - tainted = true; - - m_parentScene.AttachmentsModule.AttachObject( - remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); - //objatt.ScheduleGroupForFullUpdate(); - - if (tainted) - objatt.HasGroupChanged = true; - - // Fire after attach, so we don't get messy perms dialogs - // 3 == AttachedRez - objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3); - - // Do this last so that event listeners have access to all the effects of the attachment - m_parentScene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); - } - else - { - m_log.WarnFormat( - "[SCENE GRAPH]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", - itemID, remoteClient.Name, AttachmentPt); - } - - return objatt; - } - - return null; - } - protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) { ScenePresence newAvatar = null; -- cgit v1.1 From 315fa06c75d023ef3e4285842dd730a4d94b78d6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 23:20:38 +0000 Subject: refactor: Move another RezSingleAttachment() from Scene.Inventory to AttachmentsModule --- .../Avatar/Attachments/AttachmentsModule.cs | 31 +++++++++++++++++++++- .../Framework/Interfaces/IAttachmentsModule.cs | 18 +++++++++++-- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 25 +---------------- OpenSim/Region/Framework/Scenes/Scene.cs | 8 +++--- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 12 ++++----- 5 files changed, 57 insertions(+), 37 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 084f3c9..f54e41a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -169,7 +169,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } - public SceneObjectGroup RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + public UUID RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + { + m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); + + return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true); + } + + public UUID RezSingleAttachmentFromInventory( + IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus) + { + SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt); + + if (updateInventoryStatus) + { + if (att == null) + { + ShowDetachInUserInventory(itemID, remoteClient); + } + + SetAttachmentInventoryStatus(att, remoteClient, itemID, AttachmentPt); + } + + if (null == att) + return UUID.Zero; + else + return att.UUID; + } + + protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( + IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 1fa77e4..0222b02 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -59,13 +59,27 @@ namespace OpenSim.Region.Framework.Interfaces IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); /// - /// Rez an attachment from user inventory + /// Rez an attachment from user inventory and change inventory status to match. /// /// /// /// /// The scene object that was attached. Null if the scene object could not be found - SceneObjectGroup RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); + UUID RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); + + /// + /// Rez an attachment from user inventory + /// + /// + /// + /// + /// + /// If true, we also update the user's inventory to show that the attachment is set. If false, we do not. + /// False is required so that we don't attempt to update information when a user enters a scene with the + /// attachment already correctly set up in inventory. + /// The uuid of the scene object that was attached. Null if the scene object could not be found + UUID RezSingleAttachmentFromInventory( + IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); /// /// Update the user inventory to the attachment of an item diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index dcd92d6..41533a1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1842,35 +1842,12 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnAttach(localID, itemID, avatarID); } - /// - /// Called when the client receives a request to rez a single attachment on to the avatar from inventory - /// (RezSingleAttachmentFromInv packet). - /// - /// - /// - /// - /// - public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) - { - m_log.DebugFormat("[USER INVENTORY]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); - - SceneObjectGroup att = AttachmentsModule.RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt); - - if (att == null) - { - AttachmentsModule.ShowDetachInUserInventory(itemID, remoteClient); - return UUID.Zero; - } - - return AttachmentsModule.SetAttachmentInventoryStatus(att, remoteClient, itemID, AttachmentPt); - } - public void RezMultipleAttachments(IClientAPI remoteClient, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) { foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) { - RezSingleAttachment(remoteClient, obj.ItemID, obj.AttachmentPt); + AttachmentsModule.RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 50553dd..c510dc8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2642,13 +2642,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnRezSingleAttachmentFromInv += RezSingleAttachment; + { client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; client.OnObjectDetach += m_sceneGraph.DetachObject; if (AttachmentsModule != null) { + client.OnRezSingleAttachmentFromInv += AttachmentsModule.RezSingleAttachmentFromInventory; client.OnObjectAttach += AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; } @@ -2799,12 +2799,12 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) { - client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; - client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; + client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; client.OnObjectDetach -= m_sceneGraph.DetachObject; if (AttachmentsModule != null) { + client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; client.OnObjectAttach -= AttachmentsModule.AttachObject; client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7661f1e..317c908 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3738,7 +3738,7 @@ namespace OpenSim.Region.Framework.Scenes { if (null == m_appearance) { - m_log.WarnFormat("[ATTACHMENT] Appearance has not been initialized for agent {0}", UUID); + m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID); return; } @@ -3762,12 +3762,12 @@ namespace OpenSim.Region.Framework.Scenes try { // Rez from inventory - UUID asset = m_scene.RezSingleAttachment(ControllingClient, - itemID, (uint)p); - - m_log.InfoFormat("[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", - p, itemID, assetID, asset); + UUID asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); + m_log.InfoFormat( + "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", + p, itemID, assetID, asset); } catch (Exception e) { -- cgit v1.1 From 4b813932745775ef585a2cbca99233e57d20e13e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Mar 2010 23:21:45 +0000 Subject: minor: remove some mono compiler warnings --- OpenSim/Services/GridService/GridService.cs | 6 ++---- OpenSim/Services/GridService/HypergridLinker.cs | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 1368e46..2faf018 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -123,8 +123,7 @@ namespace OpenSim.Services.GridService if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0) { // Regions reserved for the null key cannot be taken. - // - if (region.Data["PrincipalID"] == UUID.Zero.ToString()) + if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) return "Region location us reserved"; // Treat it as an auth request @@ -132,7 +131,6 @@ namespace OpenSim.Services.GridService // NOTE: Fudging the flags value here, so these flags // should not be used elsewhere. Don't optimize // this with the later retrieval of the same flags! - // rflags |= OpenSim.Data.RegionFlags.Authenticate; } @@ -489,7 +487,7 @@ namespace OpenSim.Services.GridService f |= (OpenSim.Data.RegionFlags)val; } } - catch (Exception e) + catch (Exception) { MainConsole.Instance.Output("Error in flag specification: " + p); } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index de5df9d..58746d0 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -168,10 +168,11 @@ namespace OpenSim.Services.GridService } // Sanity check. - IPAddress ipaddr = null; + //IPAddress ipaddr = null; try { - ipaddr = Util.GetHostFromDNS(host); + //ipaddr = Util.GetHostFromDNS(host); + Util.GetHostFromDNS(host); } catch { -- cgit v1.1 From 1d14cf8c3f2ac706d7e4e9cc3a32a0dcc76d0061 Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 12 Mar 2010 21:21:28 -0800 Subject: some improvements to sculptmap alpha handling and LOD --- OpenSim/Region/Physics/Meshing/SculptMesh.cs | 1272 +++++++++++++------------- 1 file changed, 645 insertions(+), 627 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs index 4dc6e2e..11b6cd4 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs @@ -1,627 +1,645 @@ -/* - * Copyright (c) Contributors - * 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. - */ - -// to build without references to System.Drawing, comment this out -#define SYSTEM_DRAWING - -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; - -#if SYSTEM_DRAWING -using System.Drawing; -using System.Drawing.Imaging; -#endif - -namespace PrimMesher -{ - - public class SculptMesh - { - public List coords; - public List faces; - - public List viewerFaces; - public List normals; - public List uvs; - - public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; - -#if SYSTEM_DRAWING - // private Bitmap ScaleImage(Bitmap srcImage, float scale) - // { - // int sourceWidth = srcImage.Width; - // int sourceHeight = srcImage.Height; - // int sourceX = 0; - // int sourceY = 0; - - // int destX = 0; - // int destY = 0; - // int destWidth = (int)(srcImage.Width * scale); - // int destHeight = (int)(srcImage.Height * scale); - - // if (srcImage.PixelFormat == PixelFormat.Format32bppArgb) - // for (int y = 0; y < srcImage.Height; y++) - // for (int x = 0; x < srcImage.Width; x++) - // { - // Color c = srcImage.GetPixel(x, y); - // srcImage.SetPixel(x, y, Color.FromArgb(255, c.R, c.G, c.B)); - // } - - // Bitmap scaledImage = new Bitmap(destWidth, destHeight, - // PixelFormat.Format24bppRgb); - - // scaledImage.SetResolution(96.0f, 96.0f); - - // Graphics grPhoto = Graphics.FromImage(scaledImage); - // grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low; - - // grPhoto.DrawImage(srcImage, - // new Rectangle(destX, destY, destWidth, destHeight), - // new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), - // GraphicsUnit.Pixel); - - // grPhoto.Dispose(); - // return scaledImage; - // } - - - public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) - { - Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); - SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); - bitmap.Dispose(); - return sculptMesh; - } - - public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) - { - Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); - _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); - bitmap.Dispose(); - } -#endif - - /// - /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications - /// Construct a sculpt mesh from a 2D array of floats - /// - /// - /// - /// - /// - /// - /// - public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) - { - float xStep, yStep; - float uStep, vStep; - - int numYElements = zMap.GetLength(0); - int numXElements = zMap.GetLength(1); - - try - { - xStep = (xEnd - xBegin) / (float)(numXElements - 1); - yStep = (yEnd - yBegin) / (float)(numYElements - 1); - - uStep = 1.0f / (numXElements - 1); - vStep = 1.0f / (numYElements - 1); - } - catch (DivideByZeroException) - { - return; - } - - coords = new List(); - faces = new List(); - normals = new List(); - uvs = new List(); - - viewerFaces = new List(); - - int p1, p2, p3, p4; - - int x, y; - int xStart = 0, yStart = 0; - - for (y = yStart; y < numYElements; y++) - { - int rowOffset = y * numXElements; - - for (x = xStart; x < numXElements; x++) - { - /* - * p1-----p2 - * | \ f2 | - * | \ | - * | f1 \| - * p3-----p4 - */ - - p4 = rowOffset + x; - p3 = p4 - 1; - - p2 = p4 - numXElements; - p1 = p3 - numXElements; - - Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); - this.coords.Add(c); - if (viewerMode) - { - this.normals.Add(new Coord()); - this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); - } - - if (y > 0 && x > 0) - { - Face f1, f2; - - if (viewerMode) - { - f1 = new Face(p1, p4, p3, p1, p4, p3); - f1.uv1 = p1; - f1.uv2 = p4; - f1.uv3 = p3; - - f2 = new Face(p1, p2, p4, p1, p2, p4); - f2.uv1 = p1; - f2.uv2 = p2; - f2.uv3 = p4; - } - else - { - f1 = new Face(p1, p4, p3); - f2 = new Face(p1, p2, p4); - } - - this.faces.Add(f1); - this.faces.Add(f2); - } - } - } - - if (viewerMode) - calcVertexNormals(SculptType.plane, numXElements, numYElements); - } - -#if SYSTEM_DRAWING - public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) - { - _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); - } - - public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) - { - _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); - } -#endif - - public SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) - { - _SculptMesh(rows, sculptType, viewerMode, mirror, invert); - } - -#if SYSTEM_DRAWING - /// - /// converts a bitmap to a list of lists of coords, while scaling the image. - /// the scaling is done in floating point so as to allow for reduced vertex position - /// quantization as the position will be averaged between pixel values. this routine will - /// likely fail if the bitmap width and height are not powers of 2. - /// - /// - /// - /// - /// - private List> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) - { - int numRows = bitmap.Height / scale; - int numCols = bitmap.Width / scale; - List> rows = new List>(numRows); - - float pixScale = 1.0f / (scale * scale); - pixScale /= 255; - - int imageX, imageY = 0; - - int rowNdx, colNdx; - - for (rowNdx = 0; rowNdx < numRows; rowNdx++) - { - List row = new List(numCols); - for (colNdx = 0; colNdx < numCols; colNdx++) - { - imageX = colNdx * scale; - int imageYStart = rowNdx * scale; - int imageYEnd = imageYStart + scale; - int imageXEnd = imageX + scale; - float rSum = 0.0f; - float gSum = 0.0f; - float bSum = 0.0f; - for (; imageX < imageXEnd; imageX++) - { - for (imageY = imageYStart; imageY < imageYEnd; imageY++) - { - Color c = bitmap.GetPixel(imageX, imageY); - rSum += c.R; - gSum += c.G; - bSum += c.B; - } - } - if (mirror) - row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); - else - row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); - - } - rows.Add(row); - } - return rows; - } - - - void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) - { - coords = new List(); - faces = new List(); - normals = new List(); - uvs = new List(); - - sculptType = (SculptType)(((int)sculptType) & 0x07); - - if (mirror) - if (sculptType == SculptType.plane) - invert = !invert; - - float sourceScaleFactor = (float)(lod) / (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height); - - int scale = (int)(1.0f / sourceScaleFactor); - if (scale < 1) scale = 1; - - _SculptMesh(bitmap2Coords(sculptBitmap, scale, mirror), sculptType, viewerMode, mirror, invert); - } -#endif - - - void _SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) - { - coords = new List(); - faces = new List(); - normals = new List(); - uvs = new List(); - - sculptType = (SculptType)(((int)sculptType) & 0x07); - - if (mirror) - if (sculptType == SculptType.plane) - invert = !invert; - - viewerFaces = new List(); - - int width = rows[0].Count; - - int p1, p2, p3, p4; - - int imageX, imageY; - - if (sculptType != SculptType.plane) - { - for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) - rows[rowNdx].Add(rows[rowNdx][0]); - } - - Coord topPole = rows[0][width / 2]; - Coord bottomPole = rows[rows.Count - 1][width / 2]; - - if (sculptType == SculptType.sphere) - { - int count = rows[0].Count; - List topPoleRow = new List(count); - List bottomPoleRow = new List(count); - - for (int i = 0; i < count; i++) - { - topPoleRow.Add(topPole); - bottomPoleRow.Add(bottomPole); - } - rows.Insert(0, topPoleRow); - rows.Add(bottomPoleRow); - } - else if (sculptType == SculptType.torus) - rows.Add(rows[0]); - - int coordsDown = rows.Count; - int coordsAcross = rows[0].Count; - - float widthUnit = 1.0f / (coordsAcross - 1); - float heightUnit = 1.0f / (coordsDown - 1); - - for (imageY = 0; imageY < coordsDown; imageY++) - { - int rowOffset = imageY * coordsAcross; - - for (imageX = 0; imageX < coordsAcross; imageX++) - { - /* - * p1-----p2 - * | \ f2 | - * | \ | - * | f1 \| - * p3-----p4 - */ - - p4 = rowOffset + imageX; - p3 = p4 - 1; - - p2 = p4 - coordsAcross; - p1 = p3 - coordsAcross; - - this.coords.Add(rows[imageY][imageX]); - if (viewerMode) - { - this.normals.Add(new Coord()); - this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); - } - - if (imageY > 0 && imageX > 0) - { - Face f1, f2; - - if (viewerMode) - { - if (invert) - { - f1 = new Face(p1, p4, p3, p1, p4, p3); - f1.uv1 = p1; - f1.uv2 = p4; - f1.uv3 = p3; - - f2 = new Face(p1, p2, p4, p1, p2, p4); - f2.uv1 = p1; - f2.uv2 = p2; - f2.uv3 = p4; - } - else - { - f1 = new Face(p1, p3, p4, p1, p3, p4); - f1.uv1 = p1; - f1.uv2 = p3; - f1.uv3 = p4; - - f2 = new Face(p1, p4, p2, p1, p4, p2); - f2.uv1 = p1; - f2.uv2 = p4; - f2.uv3 = p2; - } - } - else - { - if (invert) - { - f1 = new Face(p1, p4, p3); - f2 = new Face(p1, p2, p4); - } - else - { - f1 = new Face(p1, p3, p4); - f2 = new Face(p1, p4, p2); - } - } - - this.faces.Add(f1); - this.faces.Add(f2); - } - } - } - - if (viewerMode) - calcVertexNormals(sculptType, coordsAcross, coordsDown); - } - - /// - /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. - /// - /// - public SculptMesh Copy() - { - return new SculptMesh(this); - } - - public SculptMesh(SculptMesh sm) - { - coords = new List(sm.coords); - faces = new List(sm.faces); - viewerFaces = new List(sm.viewerFaces); - normals = new List(sm.normals); - uvs = new List(sm.uvs); - } - - private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) - { // compute vertex normals by summing all the surface normals of all the triangles sharing - // each vertex and then normalizing - int numFaces = this.faces.Count; - for (int i = 0; i < numFaces; i++) - { - Face face = this.faces[i]; - Coord surfaceNormal = face.SurfaceNormal(this.coords); - this.normals[face.n1] += surfaceNormal; - this.normals[face.n2] += surfaceNormal; - this.normals[face.n3] += surfaceNormal; - } - - int numNormals = this.normals.Count; - for (int i = 0; i < numNormals; i++) - this.normals[i] = this.normals[i].Normalize(); - - if (sculptType != SculptType.plane) - { // blend the vertex normals at the cylinder seam - for (int y = 0; y < ySize; y++) - { - int rowOffset = y * xSize; - - this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); - } - } - - foreach (Face face in this.faces) - { - ViewerFace vf = new ViewerFace(0); - vf.v1 = this.coords[face.v1]; - vf.v2 = this.coords[face.v2]; - vf.v3 = this.coords[face.v3]; - - vf.coordIndex1 = face.v1; - vf.coordIndex2 = face.v2; - vf.coordIndex3 = face.v3; - - vf.n1 = this.normals[face.n1]; - vf.n2 = this.normals[face.n2]; - vf.n3 = this.normals[face.n3]; - - vf.uv1 = this.uvs[face.uv1]; - vf.uv2 = this.uvs[face.uv2]; - vf.uv3 = this.uvs[face.uv3]; - - this.viewerFaces.Add(vf); - } - } - - /// - /// Adds a value to each XYZ vertex coordinate in the mesh - /// - /// - /// - /// - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.AddPos(x, y, z); - this.viewerFaces[i] = v; - } - } - } - - /// - /// Rotates the mesh - /// - /// - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - int numNormals = this.normals.Count; - for (i = 0; i < numNormals; i++) - this.normals[i] *= q; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= q; - v.v2 *= q; - v.v3 *= q; - - v.n1 *= q; - v.n2 *= q; - v.n3 *= q; - - this.viewerFaces[i] = v; - } - } - } - - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= m; - v.v2 *= m; - v.v3 *= m; - this.viewerFaces[i] = v; - } - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} +/* + * Copyright (c) Contributors + * 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. + */ + +// to build without references to System.Drawing, comment this out +#define SYSTEM_DRAWING + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +#if SYSTEM_DRAWING +using System.Drawing; +using System.Drawing.Imaging; +#endif + +namespace PrimMesher +{ + + public class SculptMesh + { + public List coords; + public List faces; + + public List viewerFaces; + public List normals; + public List uvs; + + public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; + +#if SYSTEM_DRAWING + private Bitmap ScaleImage(Bitmap srcImage, float scale, bool removeAlpha) + { + int sourceWidth = srcImage.Width; + int sourceHeight = srcImage.Height; + int sourceX = 0; + int sourceY = 0; + + int destX = 0; + int destY = 0; + int destWidth = (int)(srcImage.Width * scale); + int destHeight = (int)(srcImage.Height * scale); + + Bitmap scaledImage; + + if (removeAlpha) + { + if (srcImage.PixelFormat == PixelFormat.Format32bppArgb) + for (int y = 0; y < srcImage.Height; y++) + for (int x = 0; x < srcImage.Width; x++) + { + Color c = srcImage.GetPixel(x, y); + srcImage.SetPixel(x, y, Color.FromArgb(255, c.R, c.G, c.B)); + } + + scaledImage = new Bitmap(destWidth, destHeight, + PixelFormat.Format24bppRgb); + } + else + scaledImage = new Bitmap(srcImage, destWidth, destHeight); + + scaledImage.SetResolution(96.0f, 96.0f); + + Graphics grPhoto = Graphics.FromImage(scaledImage); + grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low; + + grPhoto.DrawImage(srcImage, + new Rectangle(destX, destY, destWidth, destHeight), + new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), + GraphicsUnit.Pixel); + + grPhoto.Dispose(); + return scaledImage; + } + + + public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) + { + Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); + SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); + bitmap.Dispose(); + return sculptMesh; + } + + public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) + { + Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); + _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); + bitmap.Dispose(); + } +#endif + + /// + /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications + /// Construct a sculpt mesh from a 2D array of floats + /// + /// + /// + /// + /// + /// + /// + public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) + { + float xStep, yStep; + float uStep, vStep; + + int numYElements = zMap.GetLength(0); + int numXElements = zMap.GetLength(1); + + try + { + xStep = (xEnd - xBegin) / (float)(numXElements - 1); + yStep = (yEnd - yBegin) / (float)(numYElements - 1); + + uStep = 1.0f / (numXElements - 1); + vStep = 1.0f / (numYElements - 1); + } + catch (DivideByZeroException) + { + return; + } + + coords = new List(); + faces = new List(); + normals = new List(); + uvs = new List(); + + viewerFaces = new List(); + + int p1, p2, p3, p4; + + int x, y; + int xStart = 0, yStart = 0; + + for (y = yStart; y < numYElements; y++) + { + int rowOffset = y * numXElements; + + for (x = xStart; x < numXElements; x++) + { + /* + * p1-----p2 + * | \ f2 | + * | \ | + * | f1 \| + * p3-----p4 + */ + + p4 = rowOffset + x; + p3 = p4 - 1; + + p2 = p4 - numXElements; + p1 = p3 - numXElements; + + Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); + this.coords.Add(c); + if (viewerMode) + { + this.normals.Add(new Coord()); + this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); + } + + if (y > 0 && x > 0) + { + Face f1, f2; + + if (viewerMode) + { + f1 = new Face(p1, p4, p3, p1, p4, p3); + f1.uv1 = p1; + f1.uv2 = p4; + f1.uv3 = p3; + + f2 = new Face(p1, p2, p4, p1, p2, p4); + f2.uv1 = p1; + f2.uv2 = p2; + f2.uv3 = p4; + } + else + { + f1 = new Face(p1, p4, p3); + f2 = new Face(p1, p2, p4); + } + + this.faces.Add(f1); + this.faces.Add(f2); + } + } + } + + if (viewerMode) + calcVertexNormals(SculptType.plane, numXElements, numYElements); + } + +#if SYSTEM_DRAWING + public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) + { + _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); + } + + public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) + { + _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); + } +#endif + + public SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) + { + _SculptMesh(rows, sculptType, viewerMode, mirror, invert); + } + +#if SYSTEM_DRAWING + /// + /// converts a bitmap to a list of lists of coords, while scaling the image. + /// the scaling is done in floating point so as to allow for reduced vertex position + /// quantization as the position will be averaged between pixel values. this routine will + /// likely fail if the bitmap width and height are not powers of 2. + /// + /// + /// + /// + /// + private List> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) + { + int numRows = bitmap.Height / scale; + int numCols = bitmap.Width / scale; + List> rows = new List>(numRows); + + float pixScale = 1.0f / (scale * scale); + pixScale /= 255; + + int imageX, imageY = 0; + + int rowNdx, colNdx; + + for (rowNdx = 0; rowNdx < numRows; rowNdx++) + { + List row = new List(numCols); + for (colNdx = 0; colNdx < numCols; colNdx++) + { + imageX = colNdx * scale; + int imageYStart = rowNdx * scale; + int imageYEnd = imageYStart + scale; + int imageXEnd = imageX + scale; + float rSum = 0.0f; + float gSum = 0.0f; + float bSum = 0.0f; + for (; imageX < imageXEnd; imageX++) + { + for (imageY = imageYStart; imageY < imageYEnd; imageY++) + { + Color c = bitmap.GetPixel(imageX, imageY); + if (c.A != 255) + { + bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); + c = bitmap.GetPixel(imageX, imageY); + } + rSum += c.R; + gSum += c.G; + bSum += c.B; + } + } + if (mirror) + row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); + else + row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); + + } + rows.Add(row); + } + return rows; + } + + + void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) + { + coords = new List(); + faces = new List(); + normals = new List(); + uvs = new List(); + + sculptType = (SculptType)(((int)sculptType) & 0x07); + + if (mirror) + if (sculptType == SculptType.plane) + invert = !invert; + + float sculptBitmapLod = (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height); + + float sourceScaleFactor = (float)(lod) / sculptBitmapLod; + + float fScale = 1.0f / sourceScaleFactor; + + int iScale = (int)fScale; + if (iScale < 1) iScale = 1; + if (iScale > 2 && iScale % 2 == 0) + _SculptMesh(bitmap2Coords(ScaleImage(sculptBitmap, 64.0f / sculptBitmapLod, true), 64 / lod, mirror), sculptType, viewerMode, mirror, invert); + else + _SculptMesh(bitmap2Coords(sculptBitmap, iScale, mirror), sculptType, viewerMode, mirror, invert); + } +#endif + + + void _SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) + { + coords = new List(); + faces = new List(); + normals = new List(); + uvs = new List(); + + sculptType = (SculptType)(((int)sculptType) & 0x07); + + if (mirror) + if (sculptType == SculptType.plane) + invert = !invert; + + viewerFaces = new List(); + + int width = rows[0].Count; + + int p1, p2, p3, p4; + + int imageX, imageY; + + if (sculptType != SculptType.plane) + { + for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) + rows[rowNdx].Add(rows[rowNdx][0]); + } + + Coord topPole = rows[0][width / 2]; + Coord bottomPole = rows[rows.Count - 1][width / 2]; + + if (sculptType == SculptType.sphere) + { + int count = rows[0].Count; + List topPoleRow = new List(count); + List bottomPoleRow = new List(count); + + for (int i = 0; i < count; i++) + { + topPoleRow.Add(topPole); + bottomPoleRow.Add(bottomPole); + } + rows.Insert(0, topPoleRow); + rows.Add(bottomPoleRow); + } + else if (sculptType == SculptType.torus) + rows.Add(rows[0]); + + int coordsDown = rows.Count; + int coordsAcross = rows[0].Count; + + float widthUnit = 1.0f / (coordsAcross - 1); + float heightUnit = 1.0f / (coordsDown - 1); + + for (imageY = 0; imageY < coordsDown; imageY++) + { + int rowOffset = imageY * coordsAcross; + + for (imageX = 0; imageX < coordsAcross; imageX++) + { + /* + * p1-----p2 + * | \ f2 | + * | \ | + * | f1 \| + * p3-----p4 + */ + + p4 = rowOffset + imageX; + p3 = p4 - 1; + + p2 = p4 - coordsAcross; + p1 = p3 - coordsAcross; + + this.coords.Add(rows[imageY][imageX]); + if (viewerMode) + { + this.normals.Add(new Coord()); + this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); + } + + if (imageY > 0 && imageX > 0) + { + Face f1, f2; + + if (viewerMode) + { + if (invert) + { + f1 = new Face(p1, p4, p3, p1, p4, p3); + f1.uv1 = p1; + f1.uv2 = p4; + f1.uv3 = p3; + + f2 = new Face(p1, p2, p4, p1, p2, p4); + f2.uv1 = p1; + f2.uv2 = p2; + f2.uv3 = p4; + } + else + { + f1 = new Face(p1, p3, p4, p1, p3, p4); + f1.uv1 = p1; + f1.uv2 = p3; + f1.uv3 = p4; + + f2 = new Face(p1, p4, p2, p1, p4, p2); + f2.uv1 = p1; + f2.uv2 = p4; + f2.uv3 = p2; + } + } + else + { + if (invert) + { + f1 = new Face(p1, p4, p3); + f2 = new Face(p1, p2, p4); + } + else + { + f1 = new Face(p1, p3, p4); + f2 = new Face(p1, p4, p2); + } + } + + this.faces.Add(f1); + this.faces.Add(f2); + } + } + } + + if (viewerMode) + calcVertexNormals(sculptType, coordsAcross, coordsDown); + } + + /// + /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. + /// + /// + public SculptMesh Copy() + { + return new SculptMesh(this); + } + + public SculptMesh(SculptMesh sm) + { + coords = new List(sm.coords); + faces = new List(sm.faces); + viewerFaces = new List(sm.viewerFaces); + normals = new List(sm.normals); + uvs = new List(sm.uvs); + } + + private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) + { // compute vertex normals by summing all the surface normals of all the triangles sharing + // each vertex and then normalizing + int numFaces = this.faces.Count; + for (int i = 0; i < numFaces; i++) + { + Face face = this.faces[i]; + Coord surfaceNormal = face.SurfaceNormal(this.coords); + this.normals[face.n1] += surfaceNormal; + this.normals[face.n2] += surfaceNormal; + this.normals[face.n3] += surfaceNormal; + } + + int numNormals = this.normals.Count; + for (int i = 0; i < numNormals; i++) + this.normals[i] = this.normals[i].Normalize(); + + if (sculptType != SculptType.plane) + { // blend the vertex normals at the cylinder seam + for (int y = 0; y < ySize; y++) + { + int rowOffset = y * xSize; + + this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); + } + } + + foreach (Face face in this.faces) + { + ViewerFace vf = new ViewerFace(0); + vf.v1 = this.coords[face.v1]; + vf.v2 = this.coords[face.v2]; + vf.v3 = this.coords[face.v3]; + + vf.coordIndex1 = face.v1; + vf.coordIndex2 = face.v2; + vf.coordIndex3 = face.v3; + + vf.n1 = this.normals[face.n1]; + vf.n2 = this.normals[face.n2]; + vf.n3 = this.normals[face.n3]; + + vf.uv1 = this.uvs[face.uv1]; + vf.uv2 = this.uvs[face.uv2]; + vf.uv3 = this.uvs[face.uv3]; + + this.viewerFaces.Add(vf); + } + } + + /// + /// Adds a value to each XYZ vertex coordinate in the mesh + /// + /// + /// + /// + public void AddPos(float x, float y, float z) + { + int i; + int numVerts = this.coords.Count; + Coord vert; + + for (i = 0; i < numVerts; i++) + { + vert = this.coords[i]; + vert.X += x; + vert.Y += y; + vert.Z += z; + this.coords[i] = vert; + } + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.AddPos(x, y, z); + this.viewerFaces[i] = v; + } + } + } + + /// + /// Rotates the mesh + /// + /// + public void AddRot(Quat q) + { + int i; + int numVerts = this.coords.Count; + + for (i = 0; i < numVerts; i++) + this.coords[i] *= q; + + int numNormals = this.normals.Count; + for (i = 0; i < numNormals; i++) + this.normals[i] *= q; + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.v1 *= q; + v.v2 *= q; + v.v3 *= q; + + v.n1 *= q; + v.n2 *= q; + v.n3 *= q; + + this.viewerFaces[i] = v; + } + } + } + + public void Scale(float x, float y, float z) + { + int i; + int numVerts = this.coords.Count; + + Coord m = new Coord(x, y, z); + for (i = 0; i < numVerts; i++) + this.coords[i] *= m; + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.v1 *= m; + v.v2 *= m; + v.v3 *= m; + this.viewerFaces[i] = v; + } + } + } + + public void DumpRaw(String path, String name, String title) + { + if (path == null) + return; + String fileName = name + "_" + title + ".raw"; + String completePath = System.IO.Path.Combine(path, fileName); + StreamWriter sw = new StreamWriter(completePath); + + for (int i = 0; i < this.faces.Count; i++) + { + string s = this.coords[this.faces[i].v1].ToString(); + s += " " + this.coords[this.faces[i].v2].ToString(); + s += " " + this.coords[this.faces[i].v3].ToString(); + + sw.WriteLine(s); + } + + sw.Close(); + } + } +} -- cgit v1.1 From 41a98b902b0d95b28a5f26717150556107ca07b7 Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 12 Mar 2010 22:05:22 -0800 Subject: correct some references which could produce erroneous prim face numbers --- OpenSim/Region/Physics/Meshing/PrimMesher.cs | 4403 +++++++++++++------------- 1 file changed, 2201 insertions(+), 2202 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index 2a213c3..b75e271 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs @@ -1,2202 +1,2201 @@ -/* - * Copyright (c) Contributors - * 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.Text; -using System.IO; - -namespace PrimMesher -{ - public struct Quat - { - /// X value - public float X; - /// Y value - public float Y; - /// Z value - public float Z; - /// W value - public float W; - - public Quat(float x, float y, float z, float w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - public Quat(Coord axis, float angle) - { - axis = axis.Normalize(); - - angle *= 0.5f; - float c = (float)Math.Cos(angle); - float s = (float)Math.Sin(angle); - - X = axis.X * s; - Y = axis.Y * s; - Z = axis.Z * s; - W = c; - - Normalize(); - } - - public float Length() - { - return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); - } - - public Quat Normalize() - { - const float MAG_THRESHOLD = 0.0000001f; - float mag = Length(); - - // Catch very small rounding errors when normalizing - if (mag > MAG_THRESHOLD) - { - float oomag = 1f / mag; - X *= oomag; - Y *= oomag; - Z *= oomag; - W *= oomag; - } - else - { - X = 0f; - Y = 0f; - Z = 0f; - W = 1f; - } - - return this; - } - - public static Quat operator *(Quat q1, Quat q2) - { - float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; - float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; - float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; - float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; - return new Quat(x, y, z, w); - } - - public override string ToString() - { - return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; - } - } - - public struct Coord - { - public float X; - public float Y; - public float Z; - - public Coord(float x, float y, float z) - { - this.X = x; - this.Y = y; - this.Z = z; - } - - public float Length() - { - return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); - } - - public Coord Invert() - { - this.X = -this.X; - this.Y = -this.Y; - this.Z = -this.Z; - - return this; - } - - public Coord Normalize() - { - const float MAG_THRESHOLD = 0.0000001f; - float mag = Length(); - - // Catch very small rounding errors when normalizing - if (mag > MAG_THRESHOLD) - { - float oomag = 1.0f / mag; - this.X *= oomag; - this.Y *= oomag; - this.Z *= oomag; - } - else - { - this.X = 0.0f; - this.Y = 0.0f; - this.Z = 0.0f; - } - - return this; - } - - public override string ToString() - { - return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); - } - - public static Coord Cross(Coord c1, Coord c2) - { - return new Coord( - c1.Y * c2.Z - c2.Y * c1.Z, - c1.Z * c2.X - c2.Z * c1.X, - c1.X * c2.Y - c2.X * c1.Y - ); - } - - public static Coord operator +(Coord v, Coord a) - { - return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); - } - - public static Coord operator *(Coord v, Coord m) - { - return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); - } - - public static Coord operator *(Coord v, Quat q) - { - // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ - - Coord c2 = new Coord(0.0f, 0.0f, 0.0f); - - c2.X = q.W * q.W * v.X + - 2f * q.Y * q.W * v.Z - - 2f * q.Z * q.W * v.Y + - q.X * q.X * v.X + - 2f * q.Y * q.X * v.Y + - 2f * q.Z * q.X * v.Z - - q.Z * q.Z * v.X - - q.Y * q.Y * v.X; - - c2.Y = - 2f * q.X * q.Y * v.X + - q.Y * q.Y * v.Y + - 2f * q.Z * q.Y * v.Z + - 2f * q.W * q.Z * v.X - - q.Z * q.Z * v.Y + - q.W * q.W * v.Y - - 2f * q.X * q.W * v.Z - - q.X * q.X * v.Y; - - c2.Z = - 2f * q.X * q.Z * v.X + - 2f * q.Y * q.Z * v.Y + - q.Z * q.Z * v.Z - - 2f * q.W * q.Y * v.X - - q.Y * q.Y * v.Z + - 2f * q.W * q.X * v.Y - - q.X * q.X * v.Z + - q.W * q.W * v.Z; - - return c2; - } - } - - public struct UVCoord - { - public float U; - public float V; - - - public UVCoord(float u, float v) - { - this.U = u; - this.V = v; - } - } - - public struct Face - { - public int primFace; - - // vertices - public int v1; - public int v2; - public int v3; - - //normals - public int n1; - public int n2; - public int n3; - - // uvs - public int uv1; - public int uv2; - public int uv3; - - - public Face(int v1, int v2, int v3) - { - primFace = 0; - - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - - this.n1 = 0; - this.n2 = 0; - this.n3 = 0; - - this.uv1 = 0; - this.uv2 = 0; - this.uv3 = 0; - - } - - public Face(int v1, int v2, int v3, int n1, int n2, int n3) - { - primFace = 0; - - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - - this.n1 = n1; - this.n2 = n2; - this.n3 = n3; - - this.uv1 = 0; - this.uv2 = 0; - this.uv3 = 0; - } - - public Coord SurfaceNormal(List coordList) - { - Coord c1 = coordList[this.v1]; - Coord c2 = coordList[this.v2]; - Coord c3 = coordList[this.v3]; - - Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); - Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); - - return Coord.Cross(edge1, edge2).Normalize(); - } - } - - public struct ViewerFace - { - public int primFaceNumber; - - public Coord v1; - public Coord v2; - public Coord v3; - - public int coordIndex1; - public int coordIndex2; - public int coordIndex3; - - public Coord n1; - public Coord n2; - public Coord n3; - - public UVCoord uv1; - public UVCoord uv2; - public UVCoord uv3; - - public ViewerFace(int primFaceNumber) - { - this.primFaceNumber = primFaceNumber; - - this.v1 = new Coord(); - this.v2 = new Coord(); - this.v3 = new Coord(); - - this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet - - this.n1 = new Coord(); - this.n2 = new Coord(); - this.n3 = new Coord(); - - this.uv1 = new UVCoord(); - this.uv2 = new UVCoord(); - this.uv3 = new UVCoord(); - } - - public void Scale(float x, float y, float z) - { - this.v1.X *= x; - this.v1.Y *= y; - this.v1.Z *= z; - - this.v2.X *= x; - this.v2.Y *= y; - this.v2.Z *= z; - - this.v3.X *= x; - this.v3.Y *= y; - this.v3.Z *= z; - } - - public void AddPos(float x, float y, float z) - { - this.v1.X += x; - this.v2.X += x; - this.v3.X += x; - - this.v1.Y += y; - this.v2.Y += y; - this.v3.Y += y; - - this.v1.Z += z; - this.v2.Z += z; - this.v3.Z += z; - } - - public void AddRot(Quat q) - { - this.v1 *= q; - this.v2 *= q; - this.v3 *= q; - - this.n1 *= q; - this.n2 *= q; - this.n3 *= q; - } - - public void CalcSurfaceNormal() - { - - Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z); - Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z); - - this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize(); - } - } - - internal struct Angle - { - internal float angle; - internal float X; - internal float Y; - - internal Angle(float angle, float x, float y) - { - this.angle = angle; - this.X = x; - this.Y = y; - } - } - - internal class AngleList - { - private float iX, iY; // intersection point - - private static Angle[] angles3 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Coord[] normals3 = - { - new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(), - new Coord(-0.5f, 0.0f, 0.0f).Normalize(), - new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(), - new Coord(0.25f, 0.4330127019f, 0.0f).Normalize() - }; - - private static Angle[] angles4 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Coord[] normals4 = - { - new Coord(0.5f, 0.5f, 0.0f).Normalize(), - new Coord(-0.5f, 0.5f, 0.0f).Normalize(), - new Coord(-0.5f, -0.5f, 0.0f).Normalize(), - new Coord(0.5f, -0.5f, 0.0f).Normalize(), - new Coord(0.5f, 0.5f, 0.0f).Normalize() - }; - - private static Angle[] angles24 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), - new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), - new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), - new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), - new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), - new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), - new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), - new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), - new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), - new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), - new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), - new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), - new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) - { - float m = (newPoint - p1.angle) / (p2.angle - p1.angle); - return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); - } - - private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) - { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ - double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); - double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); - - if (denom != 0.0) - { - double ua = uaNumerator / denom; - iX = (float)(x1 + ua * (x2 - x1)); - iY = (float)(y1 + ua * (y2 - y1)); - } - } - - internal List angles; - internal List normals; - - internal void makeAngles(int sides, float startAngle, float stopAngle) - { - angles = new List(); - normals = new List(); - - double twoPi = System.Math.PI * 2.0; - float twoPiInv = 1.0f / (float)twoPi; - - if (sides < 1) - throw new Exception("number of sides not greater than zero"); - if (stopAngle <= startAngle) - throw new Exception("stopAngle not greater than startAngle"); - - if ((sides == 3 || sides == 4 || sides == 24)) - { - startAngle *= twoPiInv; - stopAngle *= twoPiInv; - - Angle[] sourceAngles; - if (sides == 3) - sourceAngles = angles3; - else if (sides == 4) - sourceAngles = angles4; - else sourceAngles = angles24; - - int startAngleIndex = (int)(startAngle * sides); - int endAngleIndex = sourceAngles.Length - 1; - if (stopAngle < 1.0f) - endAngleIndex = (int)(stopAngle * sides) + 1; - if (endAngleIndex == startAngleIndex) - endAngleIndex++; - - for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) - { - angles.Add(sourceAngles[angleIndex]); - if (sides == 3) - normals.Add(normals3[angleIndex]); - else if (sides == 4) - normals.Add(normals4[angleIndex]); - } - - if (startAngle > 0.0f) - angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); - - if (stopAngle < 1.0f) - { - int lastAngleIndex = angles.Count - 1; - angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); - } - } - else - { - double stepSize = twoPi / sides; - - int startStep = (int)(startAngle / stepSize); - double angle = stepSize * startStep; - int step = startStep; - double stopAngleTest = stopAngle; - if (stopAngle < twoPi) - { - stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); - if (stopAngleTest < stopAngle) - stopAngleTest += stepSize; - if (stopAngleTest > twoPi) - stopAngleTest = twoPi; - } - - while (angle <= stopAngleTest) - { - Angle newAngle; - newAngle.angle = (float)angle; - newAngle.X = (float)System.Math.Cos(angle); - newAngle.Y = (float)System.Math.Sin(angle); - angles.Add(newAngle); - step += 1; - angle = stepSize * step; - } - - if (startAngle > angles[0].angle) - { - Angle newAngle; - intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); - newAngle.angle = startAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[0] = newAngle; - } - - int index = angles.Count - 1; - if (stopAngle < angles[index].angle) - { - Angle newAngle; - intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); - newAngle.angle = stopAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[index] = newAngle; - } - } - } - } - - /// - /// generates a profile for extrusion - /// - internal class Profile - { - private const float twoPi = 2.0f * (float)Math.PI; - - internal string errorMessage = null; - - internal List coords; - internal List faces; - internal List vertexNormals; - internal List us; - internal List faceUVs; - internal List faceNumbers; - - // use these for making individual meshes for each prim face - internal List outerCoordIndices = null; - internal List hollowCoordIndices = null; - internal List cut1CoordIndices = null; - internal List cut2CoordIndices = null; - - internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); - internal Coord cutNormal1 = new Coord(); - internal Coord cutNormal2 = new Coord(); - - internal int numOuterVerts = 0; - internal int numHollowVerts = 0; - - internal bool calcVertexNormals = false; - internal int bottomFaceNumber = 0; - internal int numPrimFaces = 0; - - internal Profile() - { - this.coords = new List(); - this.faces = new List(); - this.vertexNormals = new List(); - this.us = new List(); - this.faceUVs = new List(); - this.faceNumbers = new List(); - } - - internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) - { - this.calcVertexNormals = calcVertexNormals; - this.coords = new List(); - this.faces = new List(); - this.vertexNormals = new List(); - this.us = new List(); - this.faceUVs = new List(); - this.faceNumbers = new List(); - - Coord center = new Coord(0.0f, 0.0f, 0.0f); - //bool hasCenter = false; - - List hollowCoords = new List(); - List hollowNormals = new List(); - List hollowUs = new List(); - - if (calcVertexNormals) - { - this.outerCoordIndices = new List(); - this.hollowCoordIndices = new List(); - this.cut1CoordIndices = new List(); - this.cut2CoordIndices = new List(); - } - - bool hasHollow = (hollow > 0.0f); - - bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); - - AngleList angles = new AngleList(); - AngleList hollowAngles = new AngleList(); - - float xScale = 0.5f; - float yScale = 0.5f; - if (sides == 4) // corners of a square are sqrt(2) from center - { - xScale = 0.707f; - yScale = 0.707f; - } - - float startAngle = profileStart * twoPi; - float stopAngle = profileEnd * twoPi; - - try { angles.makeAngles(sides, startAngle, stopAngle); } - catch (Exception ex) - { - - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - - this.numOuterVerts = angles.angles.Count; - - // flag to create as few triangles as possible for 3 or 4 side profile - bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); - - if (hasHollow) - { - if (sides == hollowSides) - hollowAngles = angles; - else - { - try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } - catch (Exception ex) - { - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - } - this.numHollowVerts = hollowAngles.angles.Count; - } - else if (!simpleFace) - { - this.coords.Add(center); - //hasCenter = true; - if (this.calcVertexNormals) - this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); - this.us.Add(0.0f); - } - - float z = 0.0f; - - Angle angle; - Coord newVert = new Coord(); - if (hasHollow && hollowSides != sides) - { - int numHollowAngles = hollowAngles.angles.Count; - for (int i = 0; i < numHollowAngles; i++) - { - angle = hollowAngles.angles[i]; - newVert.X = hollow * xScale * angle.X; - newVert.Y = hollow * yScale * angle.Y; - newVert.Z = z; - - hollowCoords.Add(newVert); - if (this.calcVertexNormals) - { - if (hollowSides < 5) - hollowNormals.Add(hollowAngles.normals[i].Invert()); - else - hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); - - hollowUs.Add(angle.angle * hollow); - } - } - } - - int index = 0; - int numAngles = angles.angles.Count; - - for (int i = 0; i < numAngles; i++) - { - angle = angles.angles[i]; - newVert.X = angle.X * xScale; - newVert.Y = angle.Y * yScale; - newVert.Z = z; - this.coords.Add(newVert); - if (this.calcVertexNormals) - { - this.outerCoordIndices.Add(this.coords.Count - 1); - - if (sides < 5) - { - this.vertexNormals.Add(angles.normals[i]); - float u = angle.angle; - this.us.Add(u); - } - else - { - this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); - this.us.Add(angle.angle); - } - } - - if (hasHollow) - { - if (hollowSides == sides) - { - newVert.X *= hollow; - newVert.Y *= hollow; - newVert.Z = z; - hollowCoords.Add(newVert); - if (this.calcVertexNormals) - { - if (sides < 5) - { - hollowNormals.Add(angles.normals[i].Invert()); - } - - else - hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); - - hollowUs.Add(angle.angle * hollow); - } - } - } - else if (!simpleFace && createFaces && angle.angle > 0.0001f) - { - Face newFace = new Face(); - newFace.v1 = 0; - newFace.v2 = index; - newFace.v3 = index + 1; - - this.faces.Add(newFace); - } - index += 1; - } - - if (hasHollow) - { - hollowCoords.Reverse(); - if (this.calcVertexNormals) - { - hollowNormals.Reverse(); - hollowUs.Reverse(); - } - - if (createFaces) - { - int numOuterVerts = this.coords.Count; - int numHollowVerts = hollowCoords.Count; - int numTotalVerts = numOuterVerts + numHollowVerts; - - if (numOuterVerts == numHollowVerts) - { - Face newFace = new Face(); - - for (int coordIndex = 0; coordIndex < numOuterVerts - 1; coordIndex++) - { - newFace.v1 = coordIndex; - newFace.v2 = coordIndex + 1; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - - newFace.v1 = coordIndex + 1; - newFace.v2 = numTotalVerts - coordIndex - 2; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - } - } - else - { - if (numOuterVerts < numHollowVerts) - { - Face newFace = new Face(); - int j = 0; // j is the index for outer vertices - int maxJ = numOuterVerts - 1; - for (int i = 0; i < numHollowVerts; i++) // i is the index for inner vertices - { - if (j < maxJ) - if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) - { - newFace.v1 = numTotalVerts - i - 1; - newFace.v2 = j; - newFace.v3 = j + 1; - - this.faces.Add(newFace); - j += 1; - } - - newFace.v1 = j; - newFace.v2 = numTotalVerts - i - 2; - newFace.v3 = numTotalVerts - i - 1; - - this.faces.Add(newFace); - } - } - else // numHollowVerts < numOuterVerts - { - Face newFace = new Face(); - int j = 0; // j is the index for inner vertices - int maxJ = numHollowVerts - 1; - for (int i = 0; i < numOuterVerts; i++) - { - if (j < maxJ) - if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) - { - newFace.v1 = i; - newFace.v2 = numTotalVerts - j - 2; - newFace.v3 = numTotalVerts - j - 1; - - this.faces.Add(newFace); - j += 1; - } - - newFace.v1 = numTotalVerts - j - 1; - newFace.v2 = i; - newFace.v3 = i + 1; - - this.faces.Add(newFace); - } - } - } - } - - if (calcVertexNormals) - { - foreach (Coord hc in hollowCoords) - { - this.coords.Add(hc); - hollowCoordIndices.Add(this.coords.Count - 1); - } - } - else - this.coords.AddRange(hollowCoords); - - if (this.calcVertexNormals) - { - this.vertexNormals.AddRange(hollowNormals); - this.us.AddRange(hollowUs); - - } - } - - if (simpleFace && createFaces) - { - if (sides == 3) - this.faces.Add(new Face(0, 1, 2)); - else if (sides == 4) - { - this.faces.Add(new Face(0, 1, 2)); - this.faces.Add(new Face(0, 2, 3)); - } - } - - if (calcVertexNormals && hasProfileCut) - { - if (hasHollow) - { - int lastOuterVertIndex = this.numOuterVerts - 1; - - this.cut1CoordIndices.Add(0); - this.cut1CoordIndices.Add(this.coords.Count - 1); - - this.cut2CoordIndices.Add(lastOuterVertIndex + 1); - this.cut2CoordIndices.Add(lastOuterVertIndex); - - this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; - this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); - - this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; - this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); - } - - else - { - this.cutNormal1.X = this.vertexNormals[1].Y; - this.cutNormal1.Y = -this.vertexNormals[1].X; - - this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; - this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; - - } - this.cutNormal1.Normalize(); - this.cutNormal2.Normalize(); - } - - this.MakeFaceUVs(); - - hollowCoords = null; - hollowNormals = null; - hollowUs = null; - - if (calcVertexNormals) - { // calculate prim face numbers - - // face number order is top, outer, hollow, bottom, start cut, end cut - // I know it's ugly but so is the whole concept of prim face numbers - - int faceNum = 1; // start with outer faces - int startVert = hasProfileCut && !hasHollow ? 1 : 0; - if (startVert > 0) - this.faceNumbers.Add(-1); - for (int i = 0; i < numOuterVerts - 1; i++) - this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); - - //if (!hasHollow && !hasProfileCut) - // this.bottomFaceNumber = faceNum++; - - this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); - - if (sides > 4 && (hasHollow || hasProfileCut)) - faceNum++; - - if (hasHollow) - { - for (int i = 0; i < numHollowVerts; i++) - this.faceNumbers.Add(faceNum); - - faceNum++; - } - //if (hasProfileCut || hasHollow) - // this.bottomFaceNumber = faceNum++; - this.bottomFaceNumber = faceNum++; - - if (hasHollow && hasProfileCut) - this.faceNumbers.Add(faceNum++); - for (int i = 0; i < this.faceNumbers.Count; i++) - if (this.faceNumbers[i] == -1) - this.faceNumbers[i] = faceNum++; - - - this.numPrimFaces = faceNum; - } - - } - - internal void MakeFaceUVs() - { - this.faceUVs = new List(); - foreach (Coord c in this.coords) - this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y))); - } - - internal Profile Copy() - { - return this.Copy(true); - } - - internal Profile Copy(bool needFaces) - { - Profile copy = new Profile(); - - copy.coords.AddRange(this.coords); - copy.faceUVs.AddRange(this.faceUVs); - - if (needFaces) - copy.faces.AddRange(this.faces); - if ((copy.calcVertexNormals = this.calcVertexNormals) == true) - { - copy.vertexNormals.AddRange(this.vertexNormals); - copy.faceNormal = this.faceNormal; - copy.cutNormal1 = this.cutNormal1; - copy.cutNormal2 = this.cutNormal2; - copy.us.AddRange(this.us); - copy.faceNumbers.AddRange(this.faceNumbers); - - copy.cut1CoordIndices = new List(this.cut1CoordIndices); - copy.cut2CoordIndices = new List(this.cut2CoordIndices); - copy.hollowCoordIndices = new List(this.hollowCoordIndices); - copy.outerCoordIndices = new List(this.outerCoordIndices); - } - copy.numOuterVerts = this.numOuterVerts; - copy.numHollowVerts = this.numHollowVerts; - - return copy; - } - - internal void AddPos(Coord v) - { - this.AddPos(v.X, v.Y, v.Z); - } - - internal void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - } - - internal void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - if (this.calcVertexNormals) - { - int numNormals = this.vertexNormals.Count; - for (i = 0; i < numNormals; i++) - this.vertexNormals[i] *= q; - - this.faceNormal *= q; - this.cutNormal1 *= q; - this.cutNormal2 *= q; - - } - } - - internal void Scale(float x, float y) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X *= x; - vert.Y *= y; - this.coords[i] = vert; - } - } - - /// - /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices - /// - internal void FlipNormals() - { - int i; - int numFaces = this.faces.Count; - Face tmpFace; - int tmp; - - for (i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmp = tmpFace.v3; - tmpFace.v3 = tmpFace.v1; - tmpFace.v1 = tmp; - this.faces[i] = tmpFace; - } - - if (this.calcVertexNormals) - { - int normalCount = this.vertexNormals.Count; - if (normalCount > 0) - { - Coord n = this.vertexNormals[normalCount - 1]; - n.Z = -n.Z; - this.vertexNormals[normalCount - 1] = n; - } - } - - this.faceNormal.X = -this.faceNormal.X; - this.faceNormal.Y = -this.faceNormal.Y; - this.faceNormal.Z = -this.faceNormal.Z; - - int numfaceUVs = this.faceUVs.Count; - for (i = 0; i < numfaceUVs; i++) - { - UVCoord uv = this.faceUVs[i]; - uv.V = 1.0f - uv.V; - this.faceUVs[i] = uv; - } - } - - internal void AddValue2FaceVertexIndices(int num) - { - int numFaces = this.faces.Count; - Face tmpFace; - for (int i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmpFace.v1 += num; - tmpFace.v2 += num; - tmpFace.v3 += num; - - this.faces[i] = tmpFace; - } - } - - internal void AddValue2FaceNormalIndices(int num) - { - if (this.calcVertexNormals) - { - int numFaces = this.faces.Count; - Face tmpFace; - for (int i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmpFace.n1 += num; - tmpFace.n2 += num; - tmpFace.n3 += num; - - this.faces[i] = tmpFace; - } - } - } - - internal void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } - - public struct PathNode - { - public Coord position; - public Quat rotation; - public float xScale; - public float yScale; - public float percentOfPath; - } - - public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } - - public class Path - { - public List pathNodes = new List(); - - public float twistBegin = 0.0f; - public float twistEnd = 0.0f; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private const float twoPi = 2.0f * (float)Math.PI; - - public void Create(PathType pathType, int steps) - { - if (pathType == PathType.Linear || pathType == PathType.Flexible) - { - int step = 0; - - float length = this.pathCutEnd - this.pathCutBegin; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float start = -0.5f; - float stepSize = length / (float)steps; - float percentOfPathMultiplier = stepSize; - float xOffset = 0.0f; - float yOffset = 0.0f; - float zOffset = start; - float xOffsetStepIncrement = this.topShearX / steps; - float yOffsetStepIncrement = this.topShearY / steps; - - float percentOfPath = this.pathCutBegin; - zOffset += percentOfPath; - - // sanity checks - - bool done = false; - - while (!done) - { - PathNode newNode = new PathNode(); - - newNode.xScale = 1.0f; - if (this.taperX == 0.0f) - newNode.xScale = 1.0f; - else if (this.taperX > 0.0f) - newNode.xScale = 1.0f - percentOfPath * this.taperX; - else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; - - newNode.yScale = 1.0f; - if (this.taperY == 0.0f) - newNode.yScale = 1.0f; - else if (this.taperY > 0.0f) - newNode.yScale = 1.0f - percentOfPath * this.taperY; - else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; - - float twist = twistBegin + twistTotal * percentOfPath; - - newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - newNode.position = new Coord(xOffset, yOffset, zOffset); - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - if (step < steps) - { - step += 1; - percentOfPath += percentOfPathMultiplier; - xOffset += xOffsetStepIncrement; - yOffset += yOffsetStepIncrement; - zOffset += stepSize; - if (percentOfPath > this.pathCutEnd) - done = true; - } - else done = true; - } - } // end of linear path code - - else // pathType == Circular - { - float twistTotal = twistEnd - twistBegin; - - // if the profile has a lot of twist, add more layers otherwise the layers may overlap - // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't - // accurately match the viewer - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - { - if (twistTotalAbs > Math.PI * 1.5f) - steps *= 2; - if (twistTotalAbs > Math.PI * 3.0f) - steps *= 2; - } - - float yPathScale = this.holeSizeY * 0.5f; - float pathLength = this.pathCutEnd - this.pathCutBegin; - float totalSkew = this.skew * 2.0f * pathLength; - float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; - float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); - float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; - - // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end - // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used - // to calculate the sine for generating the path radius appears to approximate it's effects there - // too, but there are some subtle differences in the radius which are noticeable as the prim size - // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on - // the meshes generated with this technique appear nearly identical in shape to the same prims when - // displayed by the viewer. - - float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; - float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; - float stepSize = twoPi / this.stepsPerRevolution; - - int step = (int)(startAngle / stepSize); -// int firstStep = step; - float angle = startAngle; - - bool done = false; - while (!done) // loop through the length of the path and add the layers - { - PathNode newNode = new PathNode(); - - float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; - float yProfileScale = this.holeSizeY; - - float percentOfPath = angle / (twoPi * this.revolutions); - float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); - - if (this.taperX > 0.01f) - xProfileScale *= 1.0f - percentOfPath * this.taperX; - else if (this.taperX < -0.01f) - xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; - - if (this.taperY > 0.01f) - yProfileScale *= 1.0f - percentOfPath * this.taperY; - else if (this.taperY < -0.01f) - yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; - - newNode.xScale = xProfileScale; - newNode.yScale = yProfileScale; - - float radiusScale = 1.0f; - if (this.radius > 0.001f) - radiusScale = 1.0f - this.radius * percentOfPath; - else if (this.radius < 0.001f) - radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); - - float twist = twistBegin + twistTotal * percentOfPath; - - float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); - xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; - - float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; - - float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; - - newNode.position = new Coord(xOffset, yOffset, zOffset); - - // now orient the rotation of the profile layer relative to it's position on the path - // adding taperY to the angle used to generate the quat appears to approximate the viewer - - newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); - - // next apply twist rotation to the profile layer - if (twistTotal != 0.0f || twistBegin != 0.0f) - newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - // calculate terms for next iteration - // calculate the angle for the next iteration of the loop - - if (angle >= endAngle - 0.01) - done = true; - else - { - step += 1; - angle = stepSize * step; - if (angle > endAngle) - angle = endAngle; - } - } - } - } - } - - public class PrimMesh - { - public string errorMessage = ""; - private const float twoPi = 2.0f * (float)Math.PI; - - public List coords; - public List normals; - public List faces; - - public List viewerFaces; - - private int sides = 4; - private int hollowSides = 4; - private float profileStart = 0.0f; - private float profileEnd = 1.0f; - private float hollow = 0.0f; - public int twistBegin = 0; - public int twistEnd = 0; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private bool hasProfileCut = false; - private bool hasHollow = false; - public bool calcVertexNormals = false; - private bool normalsProcessed = false; - public bool viewerMode = false; - - public int numPrimFaces = 0; - - /// - /// Human readable string representation of the parameters used to create a mesh. - /// - /// - public string ParamsToDisplayString() - { - string s = ""; - s += "sides..................: " + this.sides.ToString(); - s += "\nhollowSides..........: " + this.hollowSides.ToString(); - s += "\nprofileStart.........: " + this.profileStart.ToString(); - s += "\nprofileEnd...........: " + this.profileEnd.ToString(); - s += "\nhollow...............: " + this.hollow.ToString(); - s += "\ntwistBegin...........: " + this.twistBegin.ToString(); - s += "\ntwistEnd.............: " + this.twistEnd.ToString(); - s += "\ntopShearX............: " + this.topShearX.ToString(); - s += "\ntopShearY............: " + this.topShearY.ToString(); - s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); - s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); - s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); - s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); - s += "\nskew.................: " + this.skew.ToString(); - s += "\nholeSizeX............: " + this.holeSizeX.ToString(); - s += "\nholeSizeY............: " + this.holeSizeY.ToString(); - s += "\ntaperX...............: " + this.taperX.ToString(); - s += "\ntaperY...............: " + this.taperY.ToString(); - s += "\nradius...............: " + this.radius.ToString(); - s += "\nrevolutions..........: " + this.revolutions.ToString(); - s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); - - return s; - } - - /// - /// Constructs a PrimMesh object and creates the profile for extrusion. - /// - /// - /// - /// - /// - /// - public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) - { - this.coords = new List(); - this.faces = new List(); - - this.sides = sides; - this.profileStart = profileStart; - this.profileEnd = profileEnd; - this.hollow = hollow; - this.hollowSides = hollowSides; - - if (sides < 3) - this.sides = 3; - if (hollowSides < 3) - this.hollowSides = 3; - if (profileStart < 0.0f) - this.profileStart = 0.0f; - if (profileEnd > 1.0f) - this.profileEnd = 1.0f; - if (profileEnd < 0.02f) - this.profileEnd = 0.02f; - if (profileStart >= profileEnd) - this.profileStart = profileEnd - 0.02f; - if (hollow > 0.99f) - this.hollow = 0.99f; - if (hollow < 0.0f) - this.hollow = 0.0f; - - this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); - this.hasHollow = (this.hollow > 0.001f); - } - - /// - /// Extrudes a profile along a path. - /// - public void Extrude(PathType pathType) - { - this.coords = new List(); - this.faces = new List(); - - if (this.viewerMode) - { - this.viewerFaces = new List(); - this.calcVertexNormals = true; - } - - if (this.calcVertexNormals) - this.normals = new List(); - - int steps = 1; - - float length = this.pathCutEnd - this.pathCutBegin; - normalsProcessed = false; - - if (this.viewerMode && this.sides == 3) - { - // prisms don't taper well so add some vertical resolution - // other prims may benefit from this but just do prisms for now - if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01) - steps = (int)(steps * 4.5 * length); - } - - - float twistBegin = this.twistBegin / 360.0f * twoPi; - float twistEnd = this.twistEnd / 360.0f * twoPi; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float hollow = this.hollow; - - // sanity checks - float initialProfileRot = 0.0f; - if (pathType == PathType.Circular) - { - if (this.sides == 3) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 0.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides > 4) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow /= 0.7f; - } - } - } - else - { - if (this.sides == 3) - { - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 1.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides == 24 && this.hollowSides == 4) - hollow *= 1.414f; - } - - Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); - this.errorMessage = profile.errorMessage; - - this.numPrimFaces = profile.numPrimFaces; - - int cut1Vert = -1; - int cut2Vert = -1; - if (hasProfileCut) - { - cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; - cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; - } - - if (initialProfileRot != 0.0f) - { - profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); - if (viewerMode) - profile.MakeFaceUVs(); - } - - Coord lastCutNormal1 = new Coord(); - Coord lastCutNormal2 = new Coord(); - float lastV = 1.0f; - - Path path = new Path(); - path.twistBegin = twistBegin; - path.twistEnd = twistEnd; - path.topShearX = topShearX; - path.topShearY = topShearY; - path.pathCutBegin = pathCutBegin; - path.pathCutEnd = pathCutEnd; - path.dimpleBegin = dimpleBegin; - path.dimpleEnd = dimpleEnd; - path.skew = skew; - path.holeSizeX = holeSizeX; - path.holeSizeY = holeSizeY; - path.taperX = taperX; - path.taperY = taperY; - path.radius = radius; - path.revolutions = revolutions; - path.stepsPerRevolution = stepsPerRevolution; - - path.Create(pathType, steps); - - bool needEndFaces = false; - if (pathType == PathType.Circular) - { - needEndFaces = false; - if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) - needEndFaces = true; - else if (this.taperX != 0.0f || this.taperY != 0.0f) - needEndFaces = true; - else if (this.skew != 0.0f) - needEndFaces = true; - else if (twistTotal != 0.0f) - needEndFaces = true; - else if (this.radius != 0.0f) - needEndFaces = true; - } - else needEndFaces = true; - - for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - { - PathNode node = path.pathNodes[nodeIndex]; - Profile newLayer = profile.Copy(); - newLayer.Scale(node.xScale, node.yScale); - - newLayer.AddRot(node.rotation); - newLayer.AddPos(node.position); - - if (needEndFaces && nodeIndex == 0) - { - newLayer.FlipNormals(); - - // add the top faces to the viewerFaces list here - if (this.viewerMode) - { - Coord faceNormal = newLayer.faceNormal; - ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber); - int numFaces = newLayer.faces.Count; - List faces = newLayer.faces; - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - newViewerFace.v1 = newLayer.coords[face.v1]; - newViewerFace.v2 = newLayer.coords[face.v2]; - newViewerFace.v3 = newLayer.coords[face.v3]; - - newViewerFace.coordIndex1 = face.v1; - newViewerFace.coordIndex2 = face.v2; - newViewerFace.coordIndex3 = face.v3; - - newViewerFace.n1 = faceNormal; - newViewerFace.n2 = faceNormal; - newViewerFace.n3 = faceNormal; - - newViewerFace.uv1 = newLayer.faceUVs[face.v1]; - newViewerFace.uv2 = newLayer.faceUVs[face.v2]; - newViewerFace.uv3 = newLayer.faceUVs[face.v3]; - - this.viewerFaces.Add(newViewerFace); - } - } - } // if (nodeIndex == 0) - - // append this layer - - int coordsLen = this.coords.Count; -// int lastCoordsLen = coordsLen; - newLayer.AddValue2FaceVertexIndices(coordsLen); - - this.coords.AddRange(newLayer.coords); - - if (this.calcVertexNormals) - { - newLayer.AddValue2FaceNormalIndices(this.normals.Count); - this.normals.AddRange(newLayer.vertexNormals); - } - - if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f) - this.faces.AddRange(newLayer.faces); - - // fill faces between layers - - int numVerts = newLayer.coords.Count; - Face newFace = new Face(); - - if (nodeIndex > 0) - { - int startVert = coordsLen + 1; - int endVert = this.coords.Count; - - if (sides < 5 || this.hasProfileCut || hollow > 0.0f) - startVert--; - - for (int i = startVert; i < endVert; i++) - { - int iNext = i + 1; - if (i == endVert - 1) - iNext = startVert; - - int whichVert = i - startVert; - - newFace.v1 = i; - newFace.v2 = i - numVerts; - newFace.v3 = iNext - numVerts; - this.faces.Add(newFace); - - newFace.v2 = iNext - numVerts; - newFace.v3 = iNext; - this.faces.Add(newFace); - - if (this.viewerMode) - { - // add the side faces to the list of viewerFaces here - - int primFaceNum = profile.faceNumbers[whichVert]; - if (!needEndFaces) - primFaceNum -= 1; - - ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); - ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); - - float u1 = newLayer.us[whichVert]; - float u2 = 1.0f; - if (whichVert < newLayer.us.Count - 1) - u2 = newLayer.us[whichVert + 1]; - - if (whichVert == cut1Vert || whichVert == cut2Vert) - { - u1 = 0.0f; - u2 = 1.0f; - } - else if (sides < 5) - { - if (whichVert < profile.numOuterVerts) - { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled - // to reflect the entire texture width - u1 *= sides; - u2 *= sides; - u2 -= (int)u1; - u1 -= (int)u1; - if (u2 < 0.1f) - u2 = 1.0f; - } - else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) - { - u1 *= 2.0f; - u2 *= 2.0f; - } - } - - newViewerFace1.uv1.U = u1; - newViewerFace1.uv2.U = u1; - newViewerFace1.uv3.U = u2; - - newViewerFace1.uv1.V = 1.0f - node.percentOfPath; - newViewerFace1.uv2.V = lastV; - newViewerFace1.uv3.V = lastV; - - newViewerFace2.uv1.U = u1; - newViewerFace2.uv2.U = u2; - newViewerFace2.uv3.U = u2; - - newViewerFace2.uv1.V = 1.0f - node.percentOfPath; - newViewerFace2.uv2.V = lastV; - newViewerFace2.uv3.V = 1.0f - node.percentOfPath; - - newViewerFace1.v1 = this.coords[i]; - newViewerFace1.v2 = this.coords[i - numVerts]; - newViewerFace1.v3 = this.coords[iNext - numVerts]; - - newViewerFace2.v1 = this.coords[i]; - newViewerFace2.v2 = this.coords[iNext - numVerts]; - newViewerFace2.v3 = this.coords[iNext]; - - newViewerFace1.coordIndex1 = i; - newViewerFace1.coordIndex2 = i - numVerts; - newViewerFace1.coordIndex3 = iNext - numVerts; - - newViewerFace2.coordIndex1 = i; - newViewerFace2.coordIndex2 = iNext - numVerts; - newViewerFace2.coordIndex3 = iNext; - - // profile cut faces - if (whichVert == cut1Vert) - { - newViewerFace1.n1 = newLayer.cutNormal1; - newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; - - newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; - newViewerFace2.n2 = lastCutNormal1; - } - else if (whichVert == cut2Vert) - { - newViewerFace1.n1 = newLayer.cutNormal2; - newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; - - newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; - newViewerFace2.n2 = lastCutNormal2; - } - - else // outer and hollow faces - { - if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) - { // looks terrible when path is twisted... need vertex normals here - newViewerFace1.CalcSurfaceNormal(); - newViewerFace2.CalcSurfaceNormal(); - } - else - { - newViewerFace1.n1 = this.normals[i]; - newViewerFace1.n2 = this.normals[i - numVerts]; - newViewerFace1.n3 = this.normals[iNext - numVerts]; - - newViewerFace2.n1 = this.normals[i]; - newViewerFace2.n2 = this.normals[iNext - numVerts]; - newViewerFace2.n3 = this.normals[iNext]; - } - } - - this.viewerFaces.Add(newViewerFace1); - this.viewerFaces.Add(newViewerFace2); - - } - } - } - - lastCutNormal1 = newLayer.cutNormal1; - lastCutNormal2 = newLayer.cutNormal2; - lastV = 1.0f - node.percentOfPath; - - if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) - { - // add the top faces to the viewerFaces list here - Coord faceNormal = newLayer.faceNormal; - ViewerFace newViewerFace = new ViewerFace(); - newViewerFace.primFaceNumber = 0; - int numFaces = newLayer.faces.Count; - List faces = newLayer.faces; - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; - newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; - newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; - - newViewerFace.coordIndex1 = face.v1 - coordsLen; - newViewerFace.coordIndex2 = face.v2 - coordsLen; - newViewerFace.coordIndex3 = face.v3 - coordsLen; - - newViewerFace.n1 = faceNormal; - newViewerFace.n2 = faceNormal; - newViewerFace.n3 = faceNormal; - - newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; - newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; - newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; - - this.viewerFaces.Add(newViewerFace); - } - } - - - } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - - } - - - /// - /// DEPRICATED - use Extrude(PathType.Linear) instead - /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. - /// - /// - public void ExtrudeLinear() - { - this.Extrude(PathType.Linear); - } - - - /// - /// DEPRICATED - use Extrude(PathType.Circular) instead - /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. - /// - /// - public void ExtrudeCircular() - { - this.Extrude(PathType.Circular); - } - - - private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) - { - Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); - Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); - - Coord normal = Coord.Cross(edge1, edge2); - - normal.Normalize(); - - return normal; - } - - private Coord SurfaceNormal(Face face) - { - return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); - } - - /// - /// Calculate the surface normal for a face in the list of faces - /// - /// - /// - public Coord SurfaceNormal(int faceIndex) - { - int numFaces = this.faces.Count; - if (faceIndex < 0 || faceIndex >= numFaces) - throw new Exception("faceIndex out of range"); - - return SurfaceNormal(this.faces[faceIndex]); - } - - /// - /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. - /// - /// - public PrimMesh Copy() - { - PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); - copy.twistBegin = this.twistBegin; - copy.twistEnd = this.twistEnd; - copy.topShearX = this.topShearX; - copy.topShearY = this.topShearY; - copy.pathCutBegin = this.pathCutBegin; - copy.pathCutEnd = this.pathCutEnd; - copy.dimpleBegin = this.dimpleBegin; - copy.dimpleEnd = this.dimpleEnd; - copy.skew = this.skew; - copy.holeSizeX = this.holeSizeX; - copy.holeSizeY = this.holeSizeY; - copy.taperX = this.taperX; - copy.taperY = this.taperY; - copy.radius = this.radius; - copy.revolutions = this.revolutions; - copy.stepsPerRevolution = this.stepsPerRevolution; - copy.calcVertexNormals = this.calcVertexNormals; - copy.normalsProcessed = this.normalsProcessed; - copy.viewerMode = this.viewerMode; - copy.numPrimFaces = this.numPrimFaces; - copy.errorMessage = this.errorMessage; - - copy.coords = new List(this.coords); - copy.faces = new List(this.faces); - copy.viewerFaces = new List(this.viewerFaces); - copy.normals = new List(this.normals); - - return copy; - } - - /// - /// Calculate surface normals for all of the faces in the list of faces in this mesh - /// - public void CalcNormals() - { - if (normalsProcessed) - return; - - normalsProcessed = true; - - int numFaces = faces.Count; - - if (!this.calcVertexNormals) - this.normals = new List(); - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - - this.normals.Add(SurfaceNormal(i).Normalize()); - - int normIndex = normals.Count - 1; - face.n1 = normIndex; - face.n2 = normIndex; - face.n3 = normIndex; - - this.faces[i] = face; - } - } - - /// - /// Adds a value to each XYZ vertex coordinate in the mesh - /// - /// - /// - /// - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.AddPos(x, y, z); - this.viewerFaces[i] = v; - } - } - } - - /// - /// Rotates the mesh - /// - /// - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - if (this.normals != null) - { - int numNormals = this.normals.Count; - for (i = 0; i < numNormals; i++) - this.normals[i] *= q; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= q; - v.v2 *= q; - v.v3 *= q; - - v.n1 *= q; - v.n2 *= q; - v.n3 *= q; - this.viewerFaces[i] = v; - } - } - } - -#if VERTEX_INDEXER - public VertexIndexer GetVertexIndexer() - { - if (this.viewerMode && this.viewerFaces.Count > 0) - return new VertexIndexer(this); - return null; - } -#endif - - /// - /// Scales the mesh - /// - /// - /// - /// - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - //Coord vert; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= m; - v.v2 *= m; - v.v3 *= m; - this.viewerFaces[i] = v; - } - - } - - } - - /// - /// Dumps the mesh to a Blender compatible "Raw" format file - /// - /// - /// - /// - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} +/* + * Copyright (c) Contributors + * 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.Text; +using System.IO; + +namespace PrimMesher +{ + public struct Quat + { + /// X value + public float X; + /// Y value + public float Y; + /// Z value + public float Z; + /// W value + public float W; + + public Quat(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public Quat(Coord axis, float angle) + { + axis = axis.Normalize(); + + angle *= 0.5f; + float c = (float)Math.Cos(angle); + float s = (float)Math.Sin(angle); + + X = axis.X * s; + Y = axis.Y * s; + Z = axis.Z * s; + W = c; + + Normalize(); + } + + public float Length() + { + return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); + } + + public Quat Normalize() + { + const float MAG_THRESHOLD = 0.0000001f; + float mag = Length(); + + // Catch very small rounding errors when normalizing + if (mag > MAG_THRESHOLD) + { + float oomag = 1f / mag; + X *= oomag; + Y *= oomag; + Z *= oomag; + W *= oomag; + } + else + { + X = 0f; + Y = 0f; + Z = 0f; + W = 1f; + } + + return this; + } + + public static Quat operator *(Quat q1, Quat q2) + { + float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; + float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; + float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; + float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; + return new Quat(x, y, z, w); + } + + public override string ToString() + { + return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; + } + } + + public struct Coord + { + public float X; + public float Y; + public float Z; + + public Coord(float x, float y, float z) + { + this.X = x; + this.Y = y; + this.Z = z; + } + + public float Length() + { + return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); + } + + public Coord Invert() + { + this.X = -this.X; + this.Y = -this.Y; + this.Z = -this.Z; + + return this; + } + + public Coord Normalize() + { + const float MAG_THRESHOLD = 0.0000001f; + float mag = Length(); + + // Catch very small rounding errors when normalizing + if (mag > MAG_THRESHOLD) + { + float oomag = 1.0f / mag; + this.X *= oomag; + this.Y *= oomag; + this.Z *= oomag; + } + else + { + this.X = 0.0f; + this.Y = 0.0f; + this.Z = 0.0f; + } + + return this; + } + + public override string ToString() + { + return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); + } + + public static Coord Cross(Coord c1, Coord c2) + { + return new Coord( + c1.Y * c2.Z - c2.Y * c1.Z, + c1.Z * c2.X - c2.Z * c1.X, + c1.X * c2.Y - c2.X * c1.Y + ); + } + + public static Coord operator +(Coord v, Coord a) + { + return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); + } + + public static Coord operator *(Coord v, Coord m) + { + return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); + } + + public static Coord operator *(Coord v, Quat q) + { + // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ + + Coord c2 = new Coord(0.0f, 0.0f, 0.0f); + + c2.X = q.W * q.W * v.X + + 2f * q.Y * q.W * v.Z - + 2f * q.Z * q.W * v.Y + + q.X * q.X * v.X + + 2f * q.Y * q.X * v.Y + + 2f * q.Z * q.X * v.Z - + q.Z * q.Z * v.X - + q.Y * q.Y * v.X; + + c2.Y = + 2f * q.X * q.Y * v.X + + q.Y * q.Y * v.Y + + 2f * q.Z * q.Y * v.Z + + 2f * q.W * q.Z * v.X - + q.Z * q.Z * v.Y + + q.W * q.W * v.Y - + 2f * q.X * q.W * v.Z - + q.X * q.X * v.Y; + + c2.Z = + 2f * q.X * q.Z * v.X + + 2f * q.Y * q.Z * v.Y + + q.Z * q.Z * v.Z - + 2f * q.W * q.Y * v.X - + q.Y * q.Y * v.Z + + 2f * q.W * q.X * v.Y - + q.X * q.X * v.Z + + q.W * q.W * v.Z; + + return c2; + } + } + + public struct UVCoord + { + public float U; + public float V; + + + public UVCoord(float u, float v) + { + this.U = u; + this.V = v; + } + } + + public struct Face + { + public int primFace; + + // vertices + public int v1; + public int v2; + public int v3; + + //normals + public int n1; + public int n2; + public int n3; + + // uvs + public int uv1; + public int uv2; + public int uv3; + + + public Face(int v1, int v2, int v3) + { + primFace = 0; + + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + + this.n1 = 0; + this.n2 = 0; + this.n3 = 0; + + this.uv1 = 0; + this.uv2 = 0; + this.uv3 = 0; + + } + + public Face(int v1, int v2, int v3, int n1, int n2, int n3) + { + primFace = 0; + + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + + this.n1 = n1; + this.n2 = n2; + this.n3 = n3; + + this.uv1 = 0; + this.uv2 = 0; + this.uv3 = 0; + } + + public Coord SurfaceNormal(List coordList) + { + Coord c1 = coordList[this.v1]; + Coord c2 = coordList[this.v2]; + Coord c3 = coordList[this.v3]; + + Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); + Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); + + return Coord.Cross(edge1, edge2).Normalize(); + } + } + + public struct ViewerFace + { + public int primFaceNumber; + + public Coord v1; + public Coord v2; + public Coord v3; + + public int coordIndex1; + public int coordIndex2; + public int coordIndex3; + + public Coord n1; + public Coord n2; + public Coord n3; + + public UVCoord uv1; + public UVCoord uv2; + public UVCoord uv3; + + public ViewerFace(int primFaceNumber) + { + this.primFaceNumber = primFaceNumber; + + this.v1 = new Coord(); + this.v2 = new Coord(); + this.v3 = new Coord(); + + this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet + + this.n1 = new Coord(); + this.n2 = new Coord(); + this.n3 = new Coord(); + + this.uv1 = new UVCoord(); + this.uv2 = new UVCoord(); + this.uv3 = new UVCoord(); + } + + public void Scale(float x, float y, float z) + { + this.v1.X *= x; + this.v1.Y *= y; + this.v1.Z *= z; + + this.v2.X *= x; + this.v2.Y *= y; + this.v2.Z *= z; + + this.v3.X *= x; + this.v3.Y *= y; + this.v3.Z *= z; + } + + public void AddPos(float x, float y, float z) + { + this.v1.X += x; + this.v2.X += x; + this.v3.X += x; + + this.v1.Y += y; + this.v2.Y += y; + this.v3.Y += y; + + this.v1.Z += z; + this.v2.Z += z; + this.v3.Z += z; + } + + public void AddRot(Quat q) + { + this.v1 *= q; + this.v2 *= q; + this.v3 *= q; + + this.n1 *= q; + this.n2 *= q; + this.n3 *= q; + } + + public void CalcSurfaceNormal() + { + + Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z); + Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z); + + this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize(); + } + } + + internal struct Angle + { + internal float angle; + internal float X; + internal float Y; + + internal Angle(float angle, float x, float y) + { + this.angle = angle; + this.X = x; + this.Y = y; + } + } + + internal class AngleList + { + private float iX, iY; // intersection point + + private static Angle[] angles3 = + { + new Angle(0.0f, 1.0f, 0.0f), + new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), + new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), + new Angle(1.0f, 1.0f, 0.0f) + }; + + private static Coord[] normals3 = + { + new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(), + new Coord(-0.5f, 0.0f, 0.0f).Normalize(), + new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(), + new Coord(0.25f, 0.4330127019f, 0.0f).Normalize() + }; + + private static Angle[] angles4 = + { + new Angle(0.0f, 1.0f, 0.0f), + new Angle(0.25f, 0.0f, 1.0f), + new Angle(0.5f, -1.0f, 0.0f), + new Angle(0.75f, 0.0f, -1.0f), + new Angle(1.0f, 1.0f, 0.0f) + }; + + private static Coord[] normals4 = + { + new Coord(0.5f, 0.5f, 0.0f).Normalize(), + new Coord(-0.5f, 0.5f, 0.0f).Normalize(), + new Coord(-0.5f, -0.5f, 0.0f).Normalize(), + new Coord(0.5f, -0.5f, 0.0f).Normalize(), + new Coord(0.5f, 0.5f, 0.0f).Normalize() + }; + + private static Angle[] angles24 = + { + new Angle(0.0f, 1.0f, 0.0f), + new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), + new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), + new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), + new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), + new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), + new Angle(0.25f, 0.0f, 1.0f), + new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), + new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), + new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), + new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), + new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), + new Angle(0.5f, -1.0f, 0.0f), + new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), + new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), + new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), + new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), + new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), + new Angle(0.75f, 0.0f, -1.0f), + new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), + new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), + new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), + new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), + new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), + new Angle(1.0f, 1.0f, 0.0f) + }; + + private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) + { + float m = (newPoint - p1.angle) / (p2.angle - p1.angle); + return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); + } + + private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) + { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ + double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); + double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); + + if (denom != 0.0) + { + double ua = uaNumerator / denom; + iX = (float)(x1 + ua * (x2 - x1)); + iY = (float)(y1 + ua * (y2 - y1)); + } + } + + internal List angles; + internal List normals; + + internal void makeAngles(int sides, float startAngle, float stopAngle) + { + angles = new List(); + normals = new List(); + + double twoPi = System.Math.PI * 2.0; + float twoPiInv = 1.0f / (float)twoPi; + + if (sides < 1) + throw new Exception("number of sides not greater than zero"); + if (stopAngle <= startAngle) + throw new Exception("stopAngle not greater than startAngle"); + + if ((sides == 3 || sides == 4 || sides == 24)) + { + startAngle *= twoPiInv; + stopAngle *= twoPiInv; + + Angle[] sourceAngles; + if (sides == 3) + sourceAngles = angles3; + else if (sides == 4) + sourceAngles = angles4; + else sourceAngles = angles24; + + int startAngleIndex = (int)(startAngle * sides); + int endAngleIndex = sourceAngles.Length - 1; + if (stopAngle < 1.0f) + endAngleIndex = (int)(stopAngle * sides) + 1; + if (endAngleIndex == startAngleIndex) + endAngleIndex++; + + for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) + { + angles.Add(sourceAngles[angleIndex]); + if (sides == 3) + normals.Add(normals3[angleIndex]); + else if (sides == 4) + normals.Add(normals4[angleIndex]); + } + + if (startAngle > 0.0f) + angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); + + if (stopAngle < 1.0f) + { + int lastAngleIndex = angles.Count - 1; + angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); + } + } + else + { + double stepSize = twoPi / sides; + + int startStep = (int)(startAngle / stepSize); + double angle = stepSize * startStep; + int step = startStep; + double stopAngleTest = stopAngle; + if (stopAngle < twoPi) + { + stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); + if (stopAngleTest < stopAngle) + stopAngleTest += stepSize; + if (stopAngleTest > twoPi) + stopAngleTest = twoPi; + } + + while (angle <= stopAngleTest) + { + Angle newAngle; + newAngle.angle = (float)angle; + newAngle.X = (float)System.Math.Cos(angle); + newAngle.Y = (float)System.Math.Sin(angle); + angles.Add(newAngle); + step += 1; + angle = stepSize * step; + } + + if (startAngle > angles[0].angle) + { + Angle newAngle; + intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); + newAngle.angle = startAngle; + newAngle.X = iX; + newAngle.Y = iY; + angles[0] = newAngle; + } + + int index = angles.Count - 1; + if (stopAngle < angles[index].angle) + { + Angle newAngle; + intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); + newAngle.angle = stopAngle; + newAngle.X = iX; + newAngle.Y = iY; + angles[index] = newAngle; + } + } + } + } + + /// + /// generates a profile for extrusion + /// + internal class Profile + { + private const float twoPi = 2.0f * (float)Math.PI; + + internal string errorMessage = null; + + internal List coords; + internal List faces; + internal List vertexNormals; + internal List us; + internal List faceUVs; + internal List faceNumbers; + + // use these for making individual meshes for each prim face + internal List outerCoordIndices = null; + internal List hollowCoordIndices = null; + internal List cut1CoordIndices = null; + internal List cut2CoordIndices = null; + + internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); + internal Coord cutNormal1 = new Coord(); + internal Coord cutNormal2 = new Coord(); + + internal int numOuterVerts = 0; + internal int numHollowVerts = 0; + + internal bool calcVertexNormals = false; + internal int bottomFaceNumber = 0; + internal int numPrimFaces = 0; + + internal Profile() + { + this.coords = new List(); + this.faces = new List(); + this.vertexNormals = new List(); + this.us = new List(); + this.faceUVs = new List(); + this.faceNumbers = new List(); + } + + internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) + { + this.calcVertexNormals = calcVertexNormals; + this.coords = new List(); + this.faces = new List(); + this.vertexNormals = new List(); + this.us = new List(); + this.faceUVs = new List(); + this.faceNumbers = new List(); + + Coord center = new Coord(0.0f, 0.0f, 0.0f); + //bool hasCenter = false; + + List hollowCoords = new List(); + List hollowNormals = new List(); + List hollowUs = new List(); + + if (calcVertexNormals) + { + this.outerCoordIndices = new List(); + this.hollowCoordIndices = new List(); + this.cut1CoordIndices = new List(); + this.cut2CoordIndices = new List(); + } + + bool hasHollow = (hollow > 0.0f); + + bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); + + AngleList angles = new AngleList(); + AngleList hollowAngles = new AngleList(); + + float xScale = 0.5f; + float yScale = 0.5f; + if (sides == 4) // corners of a square are sqrt(2) from center + { + xScale = 0.707f; + yScale = 0.707f; + } + + float startAngle = profileStart * twoPi; + float stopAngle = profileEnd * twoPi; + + try { angles.makeAngles(sides, startAngle, stopAngle); } + catch (Exception ex) + { + + errorMessage = "makeAngles failed: Exception: " + ex.ToString() + + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); + + return; + } + + this.numOuterVerts = angles.angles.Count; + + // flag to create as few triangles as possible for 3 or 4 side profile + bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); + + if (hasHollow) + { + if (sides == hollowSides) + hollowAngles = angles; + else + { + try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } + catch (Exception ex) + { + errorMessage = "makeAngles failed: Exception: " + ex.ToString() + + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); + + return; + } + } + this.numHollowVerts = hollowAngles.angles.Count; + } + else if (!simpleFace) + { + this.coords.Add(center); + //hasCenter = true; + if (this.calcVertexNormals) + this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); + this.us.Add(0.0f); + } + + float z = 0.0f; + + Angle angle; + Coord newVert = new Coord(); + if (hasHollow && hollowSides != sides) + { + int numHollowAngles = hollowAngles.angles.Count; + for (int i = 0; i < numHollowAngles; i++) + { + angle = hollowAngles.angles[i]; + newVert.X = hollow * xScale * angle.X; + newVert.Y = hollow * yScale * angle.Y; + newVert.Z = z; + + hollowCoords.Add(newVert); + if (this.calcVertexNormals) + { + if (hollowSides < 5) + hollowNormals.Add(hollowAngles.normals[i].Invert()); + else + hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); + + hollowUs.Add(angle.angle * hollow); + } + } + } + + int index = 0; + int numAngles = angles.angles.Count; + + for (int i = 0; i < numAngles; i++) + { + angle = angles.angles[i]; + newVert.X = angle.X * xScale; + newVert.Y = angle.Y * yScale; + newVert.Z = z; + this.coords.Add(newVert); + if (this.calcVertexNormals) + { + this.outerCoordIndices.Add(this.coords.Count - 1); + + if (sides < 5) + { + this.vertexNormals.Add(angles.normals[i]); + float u = angle.angle; + this.us.Add(u); + } + else + { + this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); + this.us.Add(angle.angle); + } + } + + if (hasHollow) + { + if (hollowSides == sides) + { + newVert.X *= hollow; + newVert.Y *= hollow; + newVert.Z = z; + hollowCoords.Add(newVert); + if (this.calcVertexNormals) + { + if (sides < 5) + { + hollowNormals.Add(angles.normals[i].Invert()); + } + + else + hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); + + hollowUs.Add(angle.angle * hollow); + } + } + } + else if (!simpleFace && createFaces && angle.angle > 0.0001f) + { + Face newFace = new Face(); + newFace.v1 = 0; + newFace.v2 = index; + newFace.v3 = index + 1; + + this.faces.Add(newFace); + } + index += 1; + } + + if (hasHollow) + { + hollowCoords.Reverse(); + if (this.calcVertexNormals) + { + hollowNormals.Reverse(); + hollowUs.Reverse(); + } + + if (createFaces) + { + //int numOuterVerts = this.coords.Count; + //numOuterVerts = this.coords.Count; + //int numHollowVerts = hollowCoords.Count; + int numTotalVerts = this.numOuterVerts + this.numHollowVerts; + + if (this.numOuterVerts == this.numHollowVerts) + { + Face newFace = new Face(); + + for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++) + { + newFace.v1 = coordIndex; + newFace.v2 = coordIndex + 1; + newFace.v3 = numTotalVerts - coordIndex - 1; + this.faces.Add(newFace); + + newFace.v1 = coordIndex + 1; + newFace.v2 = numTotalVerts - coordIndex - 2; + newFace.v3 = numTotalVerts - coordIndex - 1; + this.faces.Add(newFace); + } + } + else + { + if (this.numOuterVerts < this.numHollowVerts) + { + Face newFace = new Face(); + int j = 0; // j is the index for outer vertices + int maxJ = this.numOuterVerts - 1; + for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices + { + if (j < maxJ) + if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) + { + newFace.v1 = numTotalVerts - i - 1; + newFace.v2 = j; + newFace.v3 = j + 1; + + this.faces.Add(newFace); + j += 1; + } + + newFace.v1 = j; + newFace.v2 = numTotalVerts - i - 2; + newFace.v3 = numTotalVerts - i - 1; + + this.faces.Add(newFace); + } + } + else // numHollowVerts < numOuterVerts + { + Face newFace = new Face(); + int j = 0; // j is the index for inner vertices + int maxJ = this.numHollowVerts - 1; + for (int i = 0; i < this.numOuterVerts; i++) + { + if (j < maxJ) + if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) + { + newFace.v1 = i; + newFace.v2 = numTotalVerts - j - 2; + newFace.v3 = numTotalVerts - j - 1; + + this.faces.Add(newFace); + j += 1; + } + + newFace.v1 = numTotalVerts - j - 1; + newFace.v2 = i; + newFace.v3 = i + 1; + + this.faces.Add(newFace); + } + } + } + } + + if (calcVertexNormals) + { + foreach (Coord hc in hollowCoords) + { + this.coords.Add(hc); + hollowCoordIndices.Add(this.coords.Count - 1); + } + } + else + this.coords.AddRange(hollowCoords); + + if (this.calcVertexNormals) + { + this.vertexNormals.AddRange(hollowNormals); + this.us.AddRange(hollowUs); + + } + } + + if (simpleFace && createFaces) + { + if (sides == 3) + this.faces.Add(new Face(0, 1, 2)); + else if (sides == 4) + { + this.faces.Add(new Face(0, 1, 2)); + this.faces.Add(new Face(0, 2, 3)); + } + } + + if (calcVertexNormals && hasProfileCut) + { + if (hasHollow) + { + int lastOuterVertIndex = this.numOuterVerts - 1; + + this.cut1CoordIndices.Add(0); + this.cut1CoordIndices.Add(this.coords.Count - 1); + + this.cut2CoordIndices.Add(lastOuterVertIndex + 1); + this.cut2CoordIndices.Add(lastOuterVertIndex); + + this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; + this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); + + this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; + this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); + } + + else + { + this.cutNormal1.X = this.vertexNormals[1].Y; + this.cutNormal1.Y = -this.vertexNormals[1].X; + + this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; + this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; + + } + this.cutNormal1.Normalize(); + this.cutNormal2.Normalize(); + } + + this.MakeFaceUVs(); + + hollowCoords = null; + hollowNormals = null; + hollowUs = null; + + if (calcVertexNormals) + { // calculate prim face numbers + + // face number order is top, outer, hollow, bottom, start cut, end cut + // I know it's ugly but so is the whole concept of prim face numbers + + int faceNum = 1; // start with outer faces + int startVert = hasProfileCut && !hasHollow ? 1 : 0; + if (startVert > 0) + this.faceNumbers.Add(-1); + for (int i = 0; i < this.numOuterVerts - 1; i++) + this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); + + //if (!hasHollow && !hasProfileCut) + // this.bottomFaceNumber = faceNum++; + + this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); + + if (sides > 4 && (hasHollow || hasProfileCut)) + faceNum++; + + if (hasHollow) + { + for (int i = 0; i < this.numHollowVerts; i++) + this.faceNumbers.Add(faceNum); + + faceNum++; + } + //if (hasProfileCut || hasHollow) + // this.bottomFaceNumber = faceNum++; + this.bottomFaceNumber = faceNum++; + + if (hasHollow && hasProfileCut) + this.faceNumbers.Add(faceNum++); + for (int i = 0; i < this.faceNumbers.Count; i++) + if (this.faceNumbers[i] == -1) + this.faceNumbers[i] = faceNum++; + + + this.numPrimFaces = faceNum; + } + + } + + internal void MakeFaceUVs() + { + this.faceUVs = new List(); + foreach (Coord c in this.coords) + this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y))); + } + + internal Profile Copy() + { + return this.Copy(true); + } + + internal Profile Copy(bool needFaces) + { + Profile copy = new Profile(); + + copy.coords.AddRange(this.coords); + copy.faceUVs.AddRange(this.faceUVs); + + if (needFaces) + copy.faces.AddRange(this.faces); + if ((copy.calcVertexNormals = this.calcVertexNormals) == true) + { + copy.vertexNormals.AddRange(this.vertexNormals); + copy.faceNormal = this.faceNormal; + copy.cutNormal1 = this.cutNormal1; + copy.cutNormal2 = this.cutNormal2; + copy.us.AddRange(this.us); + copy.faceNumbers.AddRange(this.faceNumbers); + + copy.cut1CoordIndices = new List(this.cut1CoordIndices); + copy.cut2CoordIndices = new List(this.cut2CoordIndices); + copy.hollowCoordIndices = new List(this.hollowCoordIndices); + copy.outerCoordIndices = new List(this.outerCoordIndices); + } + copy.numOuterVerts = this.numOuterVerts; + copy.numHollowVerts = this.numHollowVerts; + + return copy; + } + + internal void AddPos(Coord v) + { + this.AddPos(v.X, v.Y, v.Z); + } + + internal void AddPos(float x, float y, float z) + { + int i; + int numVerts = this.coords.Count; + Coord vert; + + for (i = 0; i < numVerts; i++) + { + vert = this.coords[i]; + vert.X += x; + vert.Y += y; + vert.Z += z; + this.coords[i] = vert; + } + } + + internal void AddRot(Quat q) + { + int i; + int numVerts = this.coords.Count; + + for (i = 0; i < numVerts; i++) + this.coords[i] *= q; + + if (this.calcVertexNormals) + { + int numNormals = this.vertexNormals.Count; + for (i = 0; i < numNormals; i++) + this.vertexNormals[i] *= q; + + this.faceNormal *= q; + this.cutNormal1 *= q; + this.cutNormal2 *= q; + + } + } + + internal void Scale(float x, float y) + { + int i; + int numVerts = this.coords.Count; + Coord vert; + + for (i = 0; i < numVerts; i++) + { + vert = this.coords[i]; + vert.X *= x; + vert.Y *= y; + this.coords[i] = vert; + } + } + + /// + /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices + /// + internal void FlipNormals() + { + int i; + int numFaces = this.faces.Count; + Face tmpFace; + int tmp; + + for (i = 0; i < numFaces; i++) + { + tmpFace = this.faces[i]; + tmp = tmpFace.v3; + tmpFace.v3 = tmpFace.v1; + tmpFace.v1 = tmp; + this.faces[i] = tmpFace; + } + + if (this.calcVertexNormals) + { + int normalCount = this.vertexNormals.Count; + if (normalCount > 0) + { + Coord n = this.vertexNormals[normalCount - 1]; + n.Z = -n.Z; + this.vertexNormals[normalCount - 1] = n; + } + } + + this.faceNormal.X = -this.faceNormal.X; + this.faceNormal.Y = -this.faceNormal.Y; + this.faceNormal.Z = -this.faceNormal.Z; + + int numfaceUVs = this.faceUVs.Count; + for (i = 0; i < numfaceUVs; i++) + { + UVCoord uv = this.faceUVs[i]; + uv.V = 1.0f - uv.V; + this.faceUVs[i] = uv; + } + } + + internal void AddValue2FaceVertexIndices(int num) + { + int numFaces = this.faces.Count; + Face tmpFace; + for (int i = 0; i < numFaces; i++) + { + tmpFace = this.faces[i]; + tmpFace.v1 += num; + tmpFace.v2 += num; + tmpFace.v3 += num; + + this.faces[i] = tmpFace; + } + } + + internal void AddValue2FaceNormalIndices(int num) + { + if (this.calcVertexNormals) + { + int numFaces = this.faces.Count; + Face tmpFace; + for (int i = 0; i < numFaces; i++) + { + tmpFace = this.faces[i]; + tmpFace.n1 += num; + tmpFace.n2 += num; + tmpFace.n3 += num; + + this.faces[i] = tmpFace; + } + } + } + + internal void DumpRaw(String path, String name, String title) + { + if (path == null) + return; + String fileName = name + "_" + title + ".raw"; + String completePath = System.IO.Path.Combine(path, fileName); + StreamWriter sw = new StreamWriter(completePath); + + for (int i = 0; i < this.faces.Count; i++) + { + string s = this.coords[this.faces[i].v1].ToString(); + s += " " + this.coords[this.faces[i].v2].ToString(); + s += " " + this.coords[this.faces[i].v3].ToString(); + + sw.WriteLine(s); + } + + sw.Close(); + } + } + + public struct PathNode + { + public Coord position; + public Quat rotation; + public float xScale; + public float yScale; + public float percentOfPath; + } + + public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } + + public class Path + { + public List pathNodes = new List(); + + public float twistBegin = 0.0f; + public float twistEnd = 0.0f; + public float topShearX = 0.0f; + public float topShearY = 0.0f; + public float pathCutBegin = 0.0f; + public float pathCutEnd = 1.0f; + public float dimpleBegin = 0.0f; + public float dimpleEnd = 1.0f; + public float skew = 0.0f; + public float holeSizeX = 1.0f; // called pathScaleX in pbs + public float holeSizeY = 0.25f; + public float taperX = 0.0f; + public float taperY = 0.0f; + public float radius = 0.0f; + public float revolutions = 1.0f; + public int stepsPerRevolution = 24; + + private const float twoPi = 2.0f * (float)Math.PI; + + public void Create(PathType pathType, int steps) + { + if (pathType == PathType.Linear || pathType == PathType.Flexible) + { + int step = 0; + + float length = this.pathCutEnd - this.pathCutBegin; + float twistTotal = twistEnd - twistBegin; + float twistTotalAbs = Math.Abs(twistTotal); + if (twistTotalAbs > 0.01f) + steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number + + float start = -0.5f; + float stepSize = length / (float)steps; + float percentOfPathMultiplier = stepSize; + float xOffset = 0.0f; + float yOffset = 0.0f; + float zOffset = start; + float xOffsetStepIncrement = this.topShearX / steps; + float yOffsetStepIncrement = this.topShearY / steps; + + float percentOfPath = this.pathCutBegin; + zOffset += percentOfPath; + + // sanity checks + + bool done = false; + + while (!done) + { + PathNode newNode = new PathNode(); + + newNode.xScale = 1.0f; + if (this.taperX == 0.0f) + newNode.xScale = 1.0f; + else if (this.taperX > 0.0f) + newNode.xScale = 1.0f - percentOfPath * this.taperX; + else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; + + newNode.yScale = 1.0f; + if (this.taperY == 0.0f) + newNode.yScale = 1.0f; + else if (this.taperY > 0.0f) + newNode.yScale = 1.0f - percentOfPath * this.taperY; + else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; + + float twist = twistBegin + twistTotal * percentOfPath; + + newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); + newNode.position = new Coord(xOffset, yOffset, zOffset); + newNode.percentOfPath = percentOfPath; + + pathNodes.Add(newNode); + + if (step < steps) + { + step += 1; + percentOfPath += percentOfPathMultiplier; + xOffset += xOffsetStepIncrement; + yOffset += yOffsetStepIncrement; + zOffset += stepSize; + if (percentOfPath > this.pathCutEnd) + done = true; + } + else done = true; + } + } // end of linear path code + + else // pathType == Circular + { + float twistTotal = twistEnd - twistBegin; + + // if the profile has a lot of twist, add more layers otherwise the layers may overlap + // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't + // accurately match the viewer + float twistTotalAbs = Math.Abs(twistTotal); + if (twistTotalAbs > 0.01f) + { + if (twistTotalAbs > Math.PI * 1.5f) + steps *= 2; + if (twistTotalAbs > Math.PI * 3.0f) + steps *= 2; + } + + float yPathScale = this.holeSizeY * 0.5f; + float pathLength = this.pathCutEnd - this.pathCutBegin; + float totalSkew = this.skew * 2.0f * pathLength; + float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; + float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); + float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; + + // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end + // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used + // to calculate the sine for generating the path radius appears to approximate it's effects there + // too, but there are some subtle differences in the radius which are noticeable as the prim size + // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on + // the meshes generated with this technique appear nearly identical in shape to the same prims when + // displayed by the viewer. + + float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; + float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; + float stepSize = twoPi / this.stepsPerRevolution; + + int step = (int)(startAngle / stepSize); + float angle = startAngle; + + bool done = false; + while (!done) // loop through the length of the path and add the layers + { + PathNode newNode = new PathNode(); + + float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; + float yProfileScale = this.holeSizeY; + + float percentOfPath = angle / (twoPi * this.revolutions); + float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); + + if (this.taperX > 0.01f) + xProfileScale *= 1.0f - percentOfPath * this.taperX; + else if (this.taperX < -0.01f) + xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; + + if (this.taperY > 0.01f) + yProfileScale *= 1.0f - percentOfPath * this.taperY; + else if (this.taperY < -0.01f) + yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; + + newNode.xScale = xProfileScale; + newNode.yScale = yProfileScale; + + float radiusScale = 1.0f; + if (this.radius > 0.001f) + radiusScale = 1.0f - this.radius * percentOfPath; + else if (this.radius < 0.001f) + radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); + + float twist = twistBegin + twistTotal * percentOfPath; + + float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); + xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; + + float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; + + float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; + + newNode.position = new Coord(xOffset, yOffset, zOffset); + + // now orient the rotation of the profile layer relative to it's position on the path + // adding taperY to the angle used to generate the quat appears to approximate the viewer + + newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); + + // next apply twist rotation to the profile layer + if (twistTotal != 0.0f || twistBegin != 0.0f) + newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); + + newNode.percentOfPath = percentOfPath; + + pathNodes.Add(newNode); + + // calculate terms for next iteration + // calculate the angle for the next iteration of the loop + + if (angle >= endAngle - 0.01) + done = true; + else + { + step += 1; + angle = stepSize * step; + if (angle > endAngle) + angle = endAngle; + } + } + } + } + } + + public class PrimMesh + { + public string errorMessage = ""; + private const float twoPi = 2.0f * (float)Math.PI; + + public List coords; + public List normals; + public List faces; + + public List viewerFaces; + + private int sides = 4; + private int hollowSides = 4; + private float profileStart = 0.0f; + private float profileEnd = 1.0f; + private float hollow = 0.0f; + public int twistBegin = 0; + public int twistEnd = 0; + public float topShearX = 0.0f; + public float topShearY = 0.0f; + public float pathCutBegin = 0.0f; + public float pathCutEnd = 1.0f; + public float dimpleBegin = 0.0f; + public float dimpleEnd = 1.0f; + public float skew = 0.0f; + public float holeSizeX = 1.0f; // called pathScaleX in pbs + public float holeSizeY = 0.25f; + public float taperX = 0.0f; + public float taperY = 0.0f; + public float radius = 0.0f; + public float revolutions = 1.0f; + public int stepsPerRevolution = 24; + + private bool hasProfileCut = false; + private bool hasHollow = false; + public bool calcVertexNormals = false; + private bool normalsProcessed = false; + public bool viewerMode = false; + + public int numPrimFaces = 0; + + /// + /// Human readable string representation of the parameters used to create a mesh. + /// + /// + public string ParamsToDisplayString() + { + string s = ""; + s += "sides..................: " + this.sides.ToString(); + s += "\nhollowSides..........: " + this.hollowSides.ToString(); + s += "\nprofileStart.........: " + this.profileStart.ToString(); + s += "\nprofileEnd...........: " + this.profileEnd.ToString(); + s += "\nhollow...............: " + this.hollow.ToString(); + s += "\ntwistBegin...........: " + this.twistBegin.ToString(); + s += "\ntwistEnd.............: " + this.twistEnd.ToString(); + s += "\ntopShearX............: " + this.topShearX.ToString(); + s += "\ntopShearY............: " + this.topShearY.ToString(); + s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); + s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); + s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); + s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); + s += "\nskew.................: " + this.skew.ToString(); + s += "\nholeSizeX............: " + this.holeSizeX.ToString(); + s += "\nholeSizeY............: " + this.holeSizeY.ToString(); + s += "\ntaperX...............: " + this.taperX.ToString(); + s += "\ntaperY...............: " + this.taperY.ToString(); + s += "\nradius...............: " + this.radius.ToString(); + s += "\nrevolutions..........: " + this.revolutions.ToString(); + s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); + + return s; + } + + /// + /// Constructs a PrimMesh object and creates the profile for extrusion. + /// + /// + /// + /// + /// + /// + public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) + { + this.coords = new List(); + this.faces = new List(); + + this.sides = sides; + this.profileStart = profileStart; + this.profileEnd = profileEnd; + this.hollow = hollow; + this.hollowSides = hollowSides; + + if (sides < 3) + this.sides = 3; + if (hollowSides < 3) + this.hollowSides = 3; + if (profileStart < 0.0f) + this.profileStart = 0.0f; + if (profileEnd > 1.0f) + this.profileEnd = 1.0f; + if (profileEnd < 0.02f) + this.profileEnd = 0.02f; + if (profileStart >= profileEnd) + this.profileStart = profileEnd - 0.02f; + if (hollow > 0.99f) + this.hollow = 0.99f; + if (hollow < 0.0f) + this.hollow = 0.0f; + + this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); + this.hasHollow = (this.hollow > 0.001f); + } + + /// + /// Extrudes a profile along a path. + /// + public void Extrude(PathType pathType) + { + this.coords = new List(); + this.faces = new List(); + + if (this.viewerMode) + { + this.viewerFaces = new List(); + this.calcVertexNormals = true; + } + + if (this.calcVertexNormals) + this.normals = new List(); + + int steps = 1; + + float length = this.pathCutEnd - this.pathCutBegin; + normalsProcessed = false; + + if (this.viewerMode && this.sides == 3) + { + // prisms don't taper well so add some vertical resolution + // other prims may benefit from this but just do prisms for now + if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01) + steps = (int)(steps * 4.5 * length); + } + + + float twistBegin = this.twistBegin / 360.0f * twoPi; + float twistEnd = this.twistEnd / 360.0f * twoPi; + float twistTotal = twistEnd - twistBegin; + float twistTotalAbs = Math.Abs(twistTotal); + if (twistTotalAbs > 0.01f) + steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number + + float hollow = this.hollow; + + // sanity checks + float initialProfileRot = 0.0f; + if (pathType == PathType.Circular) + { + if (this.sides == 3) + { + initialProfileRot = (float)Math.PI; + if (this.hollowSides == 4) + { + if (hollow > 0.7f) + hollow = 0.7f; + hollow *= 0.707f; + } + else hollow *= 0.5f; + } + else if (this.sides == 4) + { + initialProfileRot = 0.25f * (float)Math.PI; + if (this.hollowSides != 4) + hollow *= 0.707f; + } + else if (this.sides > 4) + { + initialProfileRot = (float)Math.PI; + if (this.hollowSides == 4) + { + if (hollow > 0.7f) + hollow = 0.7f; + hollow /= 0.7f; + } + } + } + else + { + if (this.sides == 3) + { + if (this.hollowSides == 4) + { + if (hollow > 0.7f) + hollow = 0.7f; + hollow *= 0.707f; + } + else hollow *= 0.5f; + } + else if (this.sides == 4) + { + initialProfileRot = 1.25f * (float)Math.PI; + if (this.hollowSides != 4) + hollow *= 0.707f; + } + else if (this.sides == 24 && this.hollowSides == 4) + hollow *= 1.414f; + } + + Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); + this.errorMessage = profile.errorMessage; + + this.numPrimFaces = profile.numPrimFaces; + + int cut1Vert = -1; + int cut2Vert = -1; + if (hasProfileCut) + { + cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; + cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; + } + + if (initialProfileRot != 0.0f) + { + profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); + if (viewerMode) + profile.MakeFaceUVs(); + } + + Coord lastCutNormal1 = new Coord(); + Coord lastCutNormal2 = new Coord(); + float lastV = 1.0f; + + Path path = new Path(); + path.twistBegin = twistBegin; + path.twistEnd = twistEnd; + path.topShearX = topShearX; + path.topShearY = topShearY; + path.pathCutBegin = pathCutBegin; + path.pathCutEnd = pathCutEnd; + path.dimpleBegin = dimpleBegin; + path.dimpleEnd = dimpleEnd; + path.skew = skew; + path.holeSizeX = holeSizeX; + path.holeSizeY = holeSizeY; + path.taperX = taperX; + path.taperY = taperY; + path.radius = radius; + path.revolutions = revolutions; + path.stepsPerRevolution = stepsPerRevolution; + + path.Create(pathType, steps); + + bool needEndFaces = false; + if (pathType == PathType.Circular) + { + needEndFaces = false; + if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) + needEndFaces = true; + else if (this.taperX != 0.0f || this.taperY != 0.0f) + needEndFaces = true; + else if (this.skew != 0.0f) + needEndFaces = true; + else if (twistTotal != 0.0f) + needEndFaces = true; + else if (this.radius != 0.0f) + needEndFaces = true; + } + else needEndFaces = true; + + for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) + { + PathNode node = path.pathNodes[nodeIndex]; + Profile newLayer = profile.Copy(); + newLayer.Scale(node.xScale, node.yScale); + + newLayer.AddRot(node.rotation); + newLayer.AddPos(node.position); + + if (needEndFaces && nodeIndex == 0) + { + newLayer.FlipNormals(); + + // add the top faces to the viewerFaces list here + if (this.viewerMode) + { + Coord faceNormal = newLayer.faceNormal; + ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber); + int numFaces = newLayer.faces.Count; + List faces = newLayer.faces; + + for (int i = 0; i < numFaces; i++) + { + Face face = faces[i]; + newViewerFace.v1 = newLayer.coords[face.v1]; + newViewerFace.v2 = newLayer.coords[face.v2]; + newViewerFace.v3 = newLayer.coords[face.v3]; + + newViewerFace.coordIndex1 = face.v1; + newViewerFace.coordIndex2 = face.v2; + newViewerFace.coordIndex3 = face.v3; + + newViewerFace.n1 = faceNormal; + newViewerFace.n2 = faceNormal; + newViewerFace.n3 = faceNormal; + + newViewerFace.uv1 = newLayer.faceUVs[face.v1]; + newViewerFace.uv2 = newLayer.faceUVs[face.v2]; + newViewerFace.uv3 = newLayer.faceUVs[face.v3]; + + this.viewerFaces.Add(newViewerFace); + } + } + } // if (nodeIndex == 0) + + // append this layer + + int coordsLen = this.coords.Count; + newLayer.AddValue2FaceVertexIndices(coordsLen); + + this.coords.AddRange(newLayer.coords); + + if (this.calcVertexNormals) + { + newLayer.AddValue2FaceNormalIndices(this.normals.Count); + this.normals.AddRange(newLayer.vertexNormals); + } + + if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f) + this.faces.AddRange(newLayer.faces); + + // fill faces between layers + + int numVerts = newLayer.coords.Count; + Face newFace = new Face(); + + if (nodeIndex > 0) + { + int startVert = coordsLen + 1; + int endVert = this.coords.Count; + + if (sides < 5 || this.hasProfileCut || hollow > 0.0f) + startVert--; + + for (int i = startVert; i < endVert; i++) + { + int iNext = i + 1; + if (i == endVert - 1) + iNext = startVert; + + int whichVert = i - startVert; + + newFace.v1 = i; + newFace.v2 = i - numVerts; + newFace.v3 = iNext - numVerts; + this.faces.Add(newFace); + + newFace.v2 = iNext - numVerts; + newFace.v3 = iNext; + this.faces.Add(newFace); + + if (this.viewerMode) + { + // add the side faces to the list of viewerFaces here + + int primFaceNum = profile.faceNumbers[whichVert]; + if (!needEndFaces) + primFaceNum -= 1; + + ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); + ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); + + float u1 = newLayer.us[whichVert]; + float u2 = 1.0f; + if (whichVert < newLayer.us.Count - 1) + u2 = newLayer.us[whichVert + 1]; + + if (whichVert == cut1Vert || whichVert == cut2Vert) + { + u1 = 0.0f; + u2 = 1.0f; + } + else if (sides < 5) + { + if (whichVert < profile.numOuterVerts) + { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled + // to reflect the entire texture width + u1 *= sides; + u2 *= sides; + u2 -= (int)u1; + u1 -= (int)u1; + if (u2 < 0.1f) + u2 = 1.0f; + } + else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) + { + u1 *= 2.0f; + u2 *= 2.0f; + } + } + + newViewerFace1.uv1.U = u1; + newViewerFace1.uv2.U = u1; + newViewerFace1.uv3.U = u2; + + newViewerFace1.uv1.V = 1.0f - node.percentOfPath; + newViewerFace1.uv2.V = lastV; + newViewerFace1.uv3.V = lastV; + + newViewerFace2.uv1.U = u1; + newViewerFace2.uv2.U = u2; + newViewerFace2.uv3.U = u2; + + newViewerFace2.uv1.V = 1.0f - node.percentOfPath; + newViewerFace2.uv2.V = lastV; + newViewerFace2.uv3.V = 1.0f - node.percentOfPath; + + newViewerFace1.v1 = this.coords[i]; + newViewerFace1.v2 = this.coords[i - numVerts]; + newViewerFace1.v3 = this.coords[iNext - numVerts]; + + newViewerFace2.v1 = this.coords[i]; + newViewerFace2.v2 = this.coords[iNext - numVerts]; + newViewerFace2.v3 = this.coords[iNext]; + + newViewerFace1.coordIndex1 = i; + newViewerFace1.coordIndex2 = i - numVerts; + newViewerFace1.coordIndex3 = iNext - numVerts; + + newViewerFace2.coordIndex1 = i; + newViewerFace2.coordIndex2 = iNext - numVerts; + newViewerFace2.coordIndex3 = iNext; + + // profile cut faces + if (whichVert == cut1Vert) + { + newViewerFace1.n1 = newLayer.cutNormal1; + newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; + + newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; + newViewerFace2.n2 = lastCutNormal1; + } + else if (whichVert == cut2Vert) + { + newViewerFace1.n1 = newLayer.cutNormal2; + newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; + + newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; + newViewerFace2.n2 = lastCutNormal2; + } + + else // outer and hollow faces + { + if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) + { // looks terrible when path is twisted... need vertex normals here + newViewerFace1.CalcSurfaceNormal(); + newViewerFace2.CalcSurfaceNormal(); + } + else + { + newViewerFace1.n1 = this.normals[i]; + newViewerFace1.n2 = this.normals[i - numVerts]; + newViewerFace1.n3 = this.normals[iNext - numVerts]; + + newViewerFace2.n1 = this.normals[i]; + newViewerFace2.n2 = this.normals[iNext - numVerts]; + newViewerFace2.n3 = this.normals[iNext]; + } + } + + this.viewerFaces.Add(newViewerFace1); + this.viewerFaces.Add(newViewerFace2); + + } + } + } + + lastCutNormal1 = newLayer.cutNormal1; + lastCutNormal2 = newLayer.cutNormal2; + lastV = 1.0f - node.percentOfPath; + + if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) + { + // add the top faces to the viewerFaces list here + Coord faceNormal = newLayer.faceNormal; + ViewerFace newViewerFace = new ViewerFace(); + newViewerFace.primFaceNumber = 0; + int numFaces = newLayer.faces.Count; + List faces = newLayer.faces; + + for (int i = 0; i < numFaces; i++) + { + Face face = faces[i]; + newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; + newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; + newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; + + newViewerFace.coordIndex1 = face.v1 - coordsLen; + newViewerFace.coordIndex2 = face.v2 - coordsLen; + newViewerFace.coordIndex3 = face.v3 - coordsLen; + + newViewerFace.n1 = faceNormal; + newViewerFace.n2 = faceNormal; + newViewerFace.n3 = faceNormal; + + newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; + newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; + newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; + + this.viewerFaces.Add(newViewerFace); + } + } + + + } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) + + } + + + /// + /// DEPRICATED - use Extrude(PathType.Linear) instead + /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. + /// + /// + public void ExtrudeLinear() + { + this.Extrude(PathType.Linear); + } + + + /// + /// DEPRICATED - use Extrude(PathType.Circular) instead + /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. + /// + /// + public void ExtrudeCircular() + { + this.Extrude(PathType.Circular); + } + + + private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) + { + Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); + Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); + + Coord normal = Coord.Cross(edge1, edge2); + + normal.Normalize(); + + return normal; + } + + private Coord SurfaceNormal(Face face) + { + return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); + } + + /// + /// Calculate the surface normal for a face in the list of faces + /// + /// + /// + public Coord SurfaceNormal(int faceIndex) + { + int numFaces = this.faces.Count; + if (faceIndex < 0 || faceIndex >= numFaces) + throw new Exception("faceIndex out of range"); + + return SurfaceNormal(this.faces[faceIndex]); + } + + /// + /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. + /// + /// + public PrimMesh Copy() + { + PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); + copy.twistBegin = this.twistBegin; + copy.twistEnd = this.twistEnd; + copy.topShearX = this.topShearX; + copy.topShearY = this.topShearY; + copy.pathCutBegin = this.pathCutBegin; + copy.pathCutEnd = this.pathCutEnd; + copy.dimpleBegin = this.dimpleBegin; + copy.dimpleEnd = this.dimpleEnd; + copy.skew = this.skew; + copy.holeSizeX = this.holeSizeX; + copy.holeSizeY = this.holeSizeY; + copy.taperX = this.taperX; + copy.taperY = this.taperY; + copy.radius = this.radius; + copy.revolutions = this.revolutions; + copy.stepsPerRevolution = this.stepsPerRevolution; + copy.calcVertexNormals = this.calcVertexNormals; + copy.normalsProcessed = this.normalsProcessed; + copy.viewerMode = this.viewerMode; + copy.numPrimFaces = this.numPrimFaces; + copy.errorMessage = this.errorMessage; + + copy.coords = new List(this.coords); + copy.faces = new List(this.faces); + copy.viewerFaces = new List(this.viewerFaces); + copy.normals = new List(this.normals); + + return copy; + } + + /// + /// Calculate surface normals for all of the faces in the list of faces in this mesh + /// + public void CalcNormals() + { + if (normalsProcessed) + return; + + normalsProcessed = true; + + int numFaces = faces.Count; + + if (!this.calcVertexNormals) + this.normals = new List(); + + for (int i = 0; i < numFaces; i++) + { + Face face = faces[i]; + + this.normals.Add(SurfaceNormal(i).Normalize()); + + int normIndex = normals.Count - 1; + face.n1 = normIndex; + face.n2 = normIndex; + face.n3 = normIndex; + + this.faces[i] = face; + } + } + + /// + /// Adds a value to each XYZ vertex coordinate in the mesh + /// + /// + /// + /// + public void AddPos(float x, float y, float z) + { + int i; + int numVerts = this.coords.Count; + Coord vert; + + for (i = 0; i < numVerts; i++) + { + vert = this.coords[i]; + vert.X += x; + vert.Y += y; + vert.Z += z; + this.coords[i] = vert; + } + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.AddPos(x, y, z); + this.viewerFaces[i] = v; + } + } + } + + /// + /// Rotates the mesh + /// + /// + public void AddRot(Quat q) + { + int i; + int numVerts = this.coords.Count; + + for (i = 0; i < numVerts; i++) + this.coords[i] *= q; + + if (this.normals != null) + { + int numNormals = this.normals.Count; + for (i = 0; i < numNormals; i++) + this.normals[i] *= q; + } + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.v1 *= q; + v.v2 *= q; + v.v3 *= q; + + v.n1 *= q; + v.n2 *= q; + v.n3 *= q; + this.viewerFaces[i] = v; + } + } + } + +#if VERTEX_INDEXER + public VertexIndexer GetVertexIndexer() + { + if (this.viewerMode && this.viewerFaces.Count > 0) + return new VertexIndexer(this); + return null; + } +#endif + + /// + /// Scales the mesh + /// + /// + /// + /// + public void Scale(float x, float y, float z) + { + int i; + int numVerts = this.coords.Count; + //Coord vert; + + Coord m = new Coord(x, y, z); + for (i = 0; i < numVerts; i++) + this.coords[i] *= m; + + if (this.viewerFaces != null) + { + int numViewerFaces = this.viewerFaces.Count; + for (i = 0; i < numViewerFaces; i++) + { + ViewerFace v = this.viewerFaces[i]; + v.v1 *= m; + v.v2 *= m; + v.v3 *= m; + this.viewerFaces[i] = v; + } + + } + + } + + /// + /// Dumps the mesh to a Blender compatible "Raw" format file + /// + /// + /// + /// + public void DumpRaw(String path, String name, String title) + { + if (path == null) + return; + String fileName = name + "_" + title + ".raw"; + String completePath = System.IO.Path.Combine(path, fileName); + StreamWriter sw = new StreamWriter(completePath); + + for (int i = 0; i < this.faces.Count; i++) + { + string s = this.coords[this.faces[i].v1].ToString(); + s += " " + this.coords[this.faces[i].v2].ToString(); + s += " " + this.coords[this.faces[i].v3].ToString(); + + sw.WriteLine(s); + } + + sw.Close(); + } + } +} -- cgit v1.1 From 2ebc4be99d20269dd3cc261022f5f760b54fde6c Mon Sep 17 00:00:00 2001 From: dahlia Date: Sat, 13 Mar 2010 12:04:49 -0800 Subject: add a null check in ScenePresence constructor --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 317c908..6f16ff3 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -676,7 +676,8 @@ namespace OpenSim.Region.Framework.Scenes UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); - m_userLevel = account.UserLevel; + if (account != null) + m_userLevel = account.UserLevel; IGroupsModule gm = m_scene.RequestModuleInterface(); if (gm != null) -- cgit v1.1 From 1e73e16fd0743ae193c59d7ba353158d30874784 Mon Sep 17 00:00:00 2001 From: dahlia Date: Sat, 13 Mar 2010 18:41:36 -0800 Subject: flip UVs for profile faces --- OpenSim/Region/Physics/Meshing/PrimMesher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index b75e271..6e9654b 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs @@ -1020,7 +1020,7 @@ namespace PrimMesher { this.faceUVs = new List(); foreach (Coord c in this.coords) - this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y))); + this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); } internal Profile Copy() -- cgit v1.1