diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index 5b71897ced..bb23fc1b56 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -57,6 +57,11 @@ namespace OpenSim.Data.SQLite private SqliteConnection m_conn; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + override public void Dispose() { if (m_conn != null) @@ -83,8 +88,7 @@ namespace OpenSim.Data.SQLite m_conn = new SqliteConnection(dbconnect); m_conn.Open(); - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "AssetStore"); + Migration m = new Migration(m_conn, Assembly, "AssetStore"); m.Update(); return; diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs index c3b65bbaa2..f51aa288d4 100644 --- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs @@ -53,6 +53,11 @@ namespace OpenSim.Data.SQLite protected static SqliteConnection m_Connection; private static bool m_initialized = false; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public SQLiteAuthenticationData(string connectionString, string realm) : base(connectionString) { @@ -63,7 +68,7 @@ namespace OpenSim.Data.SQLite m_Connection = new SqliteConnection(connectionString); m_Connection.Open(); - Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); + Migration m = new Migration(m_Connection, Assembly, "AuthStore"); m.Update(); m_initialized = true; diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs index 2f05a6e9f4..65719a63fa 100644 --- a/OpenSim/Data/SQLite/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs @@ -53,6 +53,11 @@ namespace OpenSim.Data.SQLite private Dictionary m_FieldMap = new Dictionary(); + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public SQLiteEstateStore() { } @@ -71,8 +76,7 @@ namespace OpenSim.Data.SQLite m_connection = new SqliteConnection(m_connectionString); m_connection.Open(); - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_connection, assem, "EstateStore"); + Migration m = new Migration(m_connection, Assembly, "EstateStore"); m.Update(); //m_connection.Close(); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 0d7ae1fc93..4f977a80e8 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -55,6 +55,11 @@ namespace OpenSim.Data.SQLite protected static SqliteConnection m_Connection; private static bool m_initialized; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public SQLiteGenericTableHandler(string connectionString, string realm, string storeName) : base(connectionString) { @@ -68,13 +73,12 @@ namespace OpenSim.Data.SQLite if (storeName != String.Empty) { - Assembly assem = GetType().Assembly; //SqliteConnection newConnection = // (SqliteConnection)((ICloneable)m_Connection).Clone(); //newConnection.Open(); - //Migration m = new Migration(newConnection, assem, storeName); - Migration m = new Migration(m_Connection, assem, storeName); + //Migration m = new Migration(newConnection, Assembly, storeName); + Migration m = new Migration(m_Connection, Assembly, storeName); m.Update(); //newConnection.Close(); //newConnection.Dispose(); diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index 377c680d70..5618772a41 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -74,6 +74,11 @@ namespace OpenSim.Data.SQLite private String m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public SQLiteSimulationData() { } @@ -132,8 +137,7 @@ namespace OpenSim.Data.SQLite SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); + Migration m = new Migration(m_conn, Assembly, "RegionStore"); m.Update(); lock (ds) diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 02edc30707..16f9046186 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -41,7 +41,7 @@ using OpenSim.Framework; namespace OpenSim.Data.SQLite { /// - /// A MySQL Interface for the Asset Server + /// A SQLite Interface for the Asset Server /// public class SQLiteXInventoryData : IXInventoryData { diff --git a/OpenSim/Framework/UndoStack.cs b/OpenSim/Framework/UndoStack.cs deleted file mode 100644 index fde63b1cf1..0000000000 --- a/OpenSim/Framework/UndoStack.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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; - -namespace OpenSim.Framework -{ - /// - /// Undo stack. Deletes entries beyond a certain capacity - /// - /// - [Serializable] - public class UndoStack - { - private int m_new = 1; - private int m_old = 0; - private T[] m_Undos; - - public UndoStack(int capacity) - { - m_Undos = new T[capacity + 1]; - } - - public bool IsFull - { - get { return m_new == m_old; } - } - - public int Capacity - { - get { return m_Undos.Length - 1; } - } - - public int Count - { - get - { - int count = m_new - m_old - 1; - if (count < 0) - count += m_Undos.Length; - return count; - } - } - - public void Push(T item) - { - if (IsFull) - { - m_old++; - if (m_old >= m_Undos.Length) - m_old -= m_Undos.Length; - } - if (++m_new >= m_Undos.Length) - m_new -= m_Undos.Length; - m_Undos[m_new] = item; - } - - public T Pop() - { - if (Count > 0) - { - T deleted = m_Undos[m_new]; - m_Undos[m_new--] = default(T); - if (m_new < 0) - m_new += m_Undos.Length; - return deleted; - } - else - throw new InvalidOperationException("Cannot pop from empty stack"); - } - - public T Peek() - { - return m_Undos[m_new]; - } - - public void Clear() - { - if (Count > 0) - { - for (int i = 0; i < m_Undos.Length; i++) - { - m_Undos[i] = default(T); - } - m_new = 1; - m_old = 0; - } - } - } -} diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 147a0110c0..be7504f413 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -907,15 +907,6 @@ namespace OpenSim.Framework } } - public class SynchronousRestObjectPoster - { - [Obsolete] - public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj) - { - return SynchronousRestObjectRequester.MakeRequest(verb, requestUrl, obj); - } - } - public class SynchronousRestObjectRequester { private static readonly ILog m_log = @@ -981,9 +972,6 @@ namespace OpenSim.Framework { using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) { - if (resp.StatusCode == HttpStatusCode.NotFound) - return deserial; - if (resp.ContentLength != 0) { Stream respStream = resp.GetResponseStream(); @@ -993,9 +981,19 @@ namespace OpenSim.Framework } else m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); - } } + catch (WebException e) + { + HttpWebResponse hwr = (HttpWebResponse)e.Response; + + if (hwr != null && hwr.StatusCode == HttpStatusCode.NotFound) + return deserial; + else + m_log.ErrorFormat( + "[SynchronousRestObjectRequester]: WebException {0} {1} {2} {3}", + requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace); + } catch (System.InvalidOperationException) { // This is what happens when there is invalid XML diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index d3bb0bc7fa..8db4e674bf 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -331,14 +331,22 @@ namespace OpenSim.Region.ClientStack.Linden } } + /// + /// Handle a request from the client for a Uri to upload a baked texture. + /// + /// + /// + /// + /// + /// + /// The upload response if the request is successful, null otherwise. public string UploadBakedTexture(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { try { - // m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + - // m_regionName); +// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName); string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); @@ -374,6 +382,11 @@ namespace OpenSim.Region.ClientStack.Linden return null; } + /// + /// Called when a baked texture has been successfully uploaded by a client. + /// + /// + /// public void BakedTextureUploaded(UUID assetID, byte[] data) { // m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); @@ -687,7 +700,7 @@ namespace OpenSim.Region.ClientStack.Linden item.CurrentPermissions = (uint)PermissionMask.All; item.BasePermissions = (uint)PermissionMask.All; item.EveryOnePermissions = 0; - item.NextPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer); + item.NextPermissions = (uint)PermissionMask.All; item.CreationDate = Util.UnixTimeSinceEpoch(); if (AddNewInventoryItem != null) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs index c9d7ae1a07..29a9199664 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs @@ -124,7 +124,7 @@ namespace OpenSim.Region.ClientStack.Linden private Hashtable MeshUploadFlag(Hashtable mDhttpMethod) { - m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: MeshUploadFlag request"); +// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); OSDMap data = new OSDMap(); ScenePresence sp = m_scene.GetScenePresence(m_agentID); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs index b7e79cc698..b2f04f96f8 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs @@ -160,8 +160,6 @@ namespace OpenSim.Region.ClientStack.Linden } } // } - - string assetName = llsdRequest.name; string assetDes = llsdRequest.description; @@ -208,12 +206,10 @@ namespace OpenSim.Region.ClientStack.Linden return uploadResponse; } - public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, string assetType,UUID AgentID) { - sbyte assType = 0; sbyte inType = 0; @@ -266,10 +262,10 @@ namespace OpenSim.Region.ClientStack.Linden item.CurrentPermissions = (uint)PermissionMask.All; item.BasePermissions = (uint)PermissionMask.All; item.EveryOnePermissions = 0; - item.NextPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer); + item.NextPermissions = (uint)PermissionMask.All; item.CreationDate = Util.UnixTimeSinceEpoch(); m_scene.AddInventoryItem(item); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs index 15ed3b322c..8189518f9b 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs @@ -129,7 +129,7 @@ namespace OpenSim.Region.ClientStack.Linden /// - /// Parses ad request + /// Parses add request /// /// /// @@ -312,11 +312,11 @@ namespace OpenSim.Region.ClientStack.Linden primFace.RepeatV = face.ScaleT; primFace.TexMapType = (MappingType) (face.MediaFlags & 6); } + pbs.TextureEntry = tmp.GetBytes(); prim.Shape = pbs; prim.Scale = obj.Scale; - SceneObjectGroup grp = new SceneObjectGroup(); grp.SetRootPart(prim); @@ -339,8 +339,8 @@ namespace OpenSim.Region.ClientStack.Linden m_scene.AddSceneObject(grp); grp.AbsolutePosition = obj.Position; } + allparts[i] = grp; - } for (int j = 1; j < allparts.Length; j++) @@ -351,7 +351,9 @@ namespace OpenSim.Region.ClientStack.Linden } rootGroup.ScheduleGroupForFullUpdate(); - pos = m_scene.GetNewRezLocation(Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale(), false); + pos + = m_scene.GetNewRezLocation( + Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale, false); responsedata["int_response_code"] = 200; //501; //410; //404; responsedata["content_type"] = "text/plain"; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c176c2bcc0..a34ad62545 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -574,22 +574,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP return result; } + /// + /// Add a handler for the given packet type. + /// + /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// are received then please us ethe synchronous version of this method. + /// + /// + /// true if the handler was added. This is currently always the case. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler) { return AddLocalPacketHandler(packetType, handler, true); } - public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool async) + /// + /// Add a handler for the given packet type. + /// + /// + /// + /// + /// If true, when the packet is received it is handled on its own thread rather than on the main inward bound + /// packet handler thread. This vastly increases respnosiveness but some packets need to be handled + /// synchronously. + /// + /// true if the handler was added. This is currently always the case. + public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) { bool result = false; lock (m_packetHandlers) { if (!m_packetHandlers.ContainsKey(packetType)) { - m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = async }); + m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync }); result = true; } } + return result; } @@ -11200,8 +11220,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) { MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + + if (multipleupdate.AgentData.SessionID != SessionId) + return false; + +// m_log.DebugFormat( +// "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); + Scene tScene = (Scene)m_scene; for (int i = 0; i < multipleupdate.ObjectData.Length; i++) @@ -11222,7 +11247,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - // UUID partId = part.UUID; +// m_log.DebugFormat( +// "[CLIENT]: Processing block {0} type {1} for {2} {3}", +// i, block.Type, part.Name, part.LocalId); + +// // Do this once since fetch parts creates a new array. +// SceneObjectPart[] parts = part.ParentGroup.Parts; +// for (int j = 0; j < parts.Length; j++) +// { +// part.StoreUndoState(); +// parts[j].IgnoreUndoUpdate = true; +// } + UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; switch (block.Type) @@ -11237,6 +11273,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSinglePosition(localId, pos1, this); } break; + case 2: Quaternion rot1 = new Quaternion(block.Data, 0, true); @@ -11247,6 +11284,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSingleRotation(localId, rot1, this); } break; + case 3: Vector3 rotPos = new Vector3(block.Data, 0); Quaternion rot2 = new Quaternion(block.Data, 12, true); @@ -11259,6 +11297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); } break; + case 4: case 20: Vector3 scale4 = new Vector3(block.Data, 0); @@ -11270,8 +11309,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimScale(localId, scale4, this); } break; - case 5: + case 5: Vector3 scale1 = new Vector3(block.Data, 12); Vector3 pos11 = new Vector3(block.Data, 0); @@ -11288,6 +11327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + case 9: Vector3 pos2 = new Vector3(block.Data, 0); @@ -11295,10 +11335,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdateVector != null) { - handlerUpdateVector(localId, pos2, this); } break; + case 10: Quaternion rot3 = new Quaternion(block.Data, 0, true); @@ -11309,6 +11349,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimRotation(localId, rot3, this); } break; + case 11: Vector3 pos3 = new Vector3(block.Data, 0); Quaternion rot4 = new Quaternion(block.Data, 12, true); @@ -11332,6 +11373,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimGroupScale(localId, scale7, this); } break; + case 13: Vector3 scale2 = new Vector3(block.Data, 12); Vector3 pos4 = new Vector3(block.Data, 0); @@ -11351,6 +11393,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + case 29: Vector3 scale5 = new Vector3(block.Data, 12); Vector3 pos5 = new Vector3(block.Data, 0); @@ -11359,6 +11402,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdatePrimGroupScale != null) { // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + part.StoreUndoState(true); + part.IgnoreUndoUpdate = true; handlerUpdatePrimGroupScale(localId, scale5, this); handlerUpdateVector = OnUpdatePrimGroupPosition; @@ -11366,8 +11411,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerUpdateVector(localId, pos5, this); } + + part.IgnoreUndoUpdate = false; } + break; + case 21: Vector3 scale6 = new Vector3(block.Data, 12); Vector3 pos6 = new Vector3(block.Data, 0); @@ -11375,6 +11424,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimScale = OnUpdatePrimScale; if (handlerUpdatePrimScale != null) { + part.StoreUndoState(false); + part.IgnoreUndoUpdate = true; + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); handlerUpdatePrimScale(localId, scale6, this); handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; @@ -11382,15 +11434,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerUpdatePrimSinglePosition(localId, pos6, this); } + + part.IgnoreUndoUpdate = false; } break; + default: - m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); break; } + +// for (int j = 0; j < parts.Length; j++) +// parts[j].IgnoreUndoUpdate = false; } } } + return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 520d794e74..1e096109cd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -566,7 +566,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) { - m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 1955e5b681..75dbeb898e 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -180,8 +180,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } /// - /// Set appearance data (textureentry and slider settings) received from the client + /// Set appearance data (texture asset IDs and slider settings) received from the client /// + /// /// /// public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 321b38b3a3..8d055d4e89 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -173,9 +173,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { if (m_RestURL != "") { - m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId); + m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); - List msglist = SynchronousRestObjectPoster.BeginPostObject>( + List msglist + = SynchronousRestObjectRequester.MakeRequest>( "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); if (msglist == null) @@ -203,7 +204,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if ((im.offline != 0) && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) { - bool success = SynchronousRestObjectPoster.BeginPostObject( + bool success = SynchronousRestObjectRequester.MakeRequest( "POST", m_RestURL+"/SaveMessage/", im); if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index c82cfd2d75..d687e6aa01 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -196,7 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure if (!(client.Scene is Scene)) return; - Scene scene = (Scene)(client.Scene); +// Scene scene = (Scene)(client.Scene); GridInstantMessage im = null; if (m_PendingLures.TryGetValue(lureID, out im)) diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs index 079e1b6b0a..dee0ad4bfc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile if (!(s is Scene)) return; - Scene scene = (Scene)s; +// Scene scene = (Scene)s; string profileUrl = String.Empty; string aboutText = String.Empty; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 66fbcb90a4..b714f2b6ab 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -810,18 +810,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); + return null; } - for (int i = 0 ; i < objlist.Count ; i++ ) + for (int i = 0 ; i < objlist.Count; i++) { group = objlist[i]; - Vector3 storedPosition = group.AbsolutePosition; +// Vector3 storedPosition = group.AbsolutePosition; if (group.UUID == UUID.Zero) { m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); } + group.RootPart.FromFolderID = item.Folder; // If it's rezzed in world, select it. Much easier to @@ -833,6 +835,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart child in group.Parts) child.CreateSelected = true; } + group.ResetIDs(); if (attachment) diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index f15f8f6de1..b5cbcbbca7 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -68,7 +68,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring { m_scene = scene; - m_scene.AddCommand(this, "monitor report", "monitor report", "Returns a variety of statistics about the current region and/or simulator", diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 9c7b2fab9c..c8325201e6 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private ITerrainChannel m_revert; private Scene m_scene; private volatile bool m_tainted; - private readonly UndoStack m_undo = new UndoStack(5); + private readonly Stack m_undo = new Stack(5); #region ICommandableModule Members diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8195a0d996..6e666322f1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1751,8 +1751,9 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart rootPart = group.GetChildPart(group.UUID); rootPart.Flags &= ~PrimFlags.Scripted; rootPart.TrimPermissions(); - group.CheckSculptAndLoad(); - //rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); + + // Don't do this here - it will get done later on when sculpt data is loaded. +// group.CheckSculptAndLoad(); } m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); @@ -2715,12 +2716,14 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientPrimEvents(IClientAPI client) { - client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition; + client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; - client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation; - client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimRotation; + + client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; client.OnUpdatePrimSingleRotationPosition += m_sceneGraph.UpdatePrimSingleRotationPosition; + client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale; client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale; client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; @@ -2842,12 +2845,14 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) { - client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimPosition; + client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; - client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimRotation; - client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimRotation; + + client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition; + client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale; client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale; client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 7ec7ea3b46..65dc2c9cf6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -564,11 +564,13 @@ namespace OpenSim.Region.Framework.Scenes part.Undo(); } } + protected internal void HandleRedo(IClientAPI remoteClient, UUID primId) { if (primId != UUID.Zero) { SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId); + if (part != null) part.Redo(); } @@ -1210,19 +1212,20 @@ namespace OpenSim.Region.Framework.Scenes #region Client Event handlers /// - /// + /// Update the scale of an individual prim. /// /// /// /// protected internal void UpdatePrimScale(uint localID, Vector3 scale, IClientAPI remoteClient) { - SceneObjectGroup group = GetGroupByPrim(localID); - if (group != null) + SceneObjectPart part = GetSceneObjectPart(localID); + + if (part != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) { - group.Resize(scale, localID); + part.Resize(scale); } } } @@ -1234,7 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) { - group.GroupResize(scale, localID); + group.GroupResize(scale); } } } @@ -1288,19 +1291,18 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) { - group.UpdateSingleRotation(rot,pos, localID); + group.UpdateSingleRotation(rot, pos, localID); } } } - /// - /// + /// Update the rotation of a whole group. /// /// /// /// - protected internal void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient) + protected internal void UpdatePrimGroupRotation(uint localID, Quaternion rot, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) @@ -1319,7 +1321,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - protected internal void UpdatePrimRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient) + protected internal void UpdatePrimGroupRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) @@ -1350,12 +1352,12 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Update the position of the given part + /// Update the position of the given group. /// /// /// /// - public void UpdatePrimPosition(uint localID, Vector3 pos, IClientAPI remoteClient) + public void UpdatePrimGroupPosition(uint localID, Vector3 pos, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index fa23fcd8bf..b6fb5a449e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -236,6 +236,38 @@ namespace OpenSim.Region.Framework.Scenes get { return m_rootPart.RotationOffset; } } + public Vector3 GroupScale + { + get + { + Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize); + Vector3 maxScale = Vector3.Zero; + Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + Vector3 partscale = part.Scale; + Vector3 partoffset = part.OffsetPosition; + + minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; + minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; + minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; + + maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; + maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; + maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; + } + + finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; + finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; + finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; + + return finalScale; + } + } + public UUID GroupID { get { return m_rootPart.GroupID; } @@ -584,7 +616,7 @@ namespace OpenSim.Region.Framework.Scenes part.ParentID = m_rootPart.LocalId; //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); } - + ApplyPhysics(m_scene.m_physicalPrim); // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled @@ -592,34 +624,6 @@ namespace OpenSim.Region.Framework.Scenes //ScheduleGroupForFullUpdate(); } - public Vector3 GroupScale() - { - Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize); - Vector3 maxScale = Vector3.Zero; - Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); - - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - Vector3 partscale = part.Scale; - Vector3 partoffset = part.OffsetPosition; - - minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; - minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; - minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; - - maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; - maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; - maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; - } - - finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; - finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; - finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; - return finalScale; - - } public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters) { // We got a request from the inner_scene to raytrace along the Ray hRay @@ -1141,6 +1145,10 @@ namespace OpenSim.Region.Framework.Scenes public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", +// remoteClient.Name, part.Name, part.LocalId, offsetPos); + part.StoreUndoState(); part.OnGrab(offsetPos, remoteClient); } @@ -1463,17 +1471,17 @@ namespace OpenSim.Region.Framework.Scenes // Need to duplicate the physics actor as well if (part.PhysActor != null && userExposed) { - PrimitiveBaseShape pbs = part.Shape; + PrimitiveBaseShape pbs = newPart.Shape; newPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( - part.LocalId, - string.Format("{0}/{1}", part.Name, part.UUID), + string.Format("{0}/{1}", newPart.Name, newPart.UUID), pbs, - part.AbsolutePosition, - part.Scale, - part.RotationOffset, - part.PhysActor.IsPhysical); + newPart.AbsolutePosition, + newPart.Scale, + newPart.RotationOffset, + part.PhysActor.IsPhysical, + newPart.LocalId); newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); } @@ -2608,195 +2616,150 @@ namespace OpenSim.Region.Framework.Scenes #region Resize /// - /// Resize the given part + /// Resize the entire group of prims. /// /// - /// - public void Resize(Vector3 scale, uint localID) + public void GroupResize(Vector3 scale) { - if (scale.X > m_scene.m_maxNonphys) - scale.X = m_scene.m_maxNonphys; - if (scale.Y > m_scene.m_maxNonphys) - scale.Y = m_scene.m_maxNonphys; - if (scale.Z > m_scene.m_maxNonphys) - scale.Z = m_scene.m_maxNonphys; +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); - SceneObjectPart part = GetChildPart(localID); - if (part != null) + RootPart.StoreUndoState(true); + + scale.X = Math.Min(scale.X, Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); + + if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical) { - part.Resize(scale); - if (part.PhysActor != null) - { - if (part.PhysActor.IsPhysical) - { - if (scale.X > m_scene.m_maxPhys) - scale.X = m_scene.m_maxPhys; - if (scale.Y > m_scene.m_maxPhys) - scale.Y = m_scene.m_maxPhys; - if (scale.Z > m_scene.m_maxPhys) - scale.Z = m_scene.m_maxPhys; - } - part.PhysActor.Size = scale; - m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); - } - //if (part.UUID != m_rootPart.UUID) - - HasGroupChanged = true; - part.TriggerScriptChangedEvent(Changed.SCALE); - ScheduleGroupForFullUpdate(); - - //if (part.UUID == m_rootPart.UUID) - //{ - //if (m_rootPart.PhysActor != null) - //{ - //m_rootPart.PhysActor.Size = - //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z); - //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); - //} - //} + scale.X = Math.Min(scale.X, Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); } - } - public void GroupResize(Vector3 scale, uint localID) - { - SceneObjectPart part = GetChildPart(localID); - if (part != null) + float x = (scale.X / RootPart.Scale.X); + float y = (scale.Y / RootPart.Scale.Y); + float z = (scale.Z / RootPart.Scale.Z); + + SceneObjectPart[] parts; + if (x > 1.0f || y > 1.0f || z > 1.0f) { - part.IgnoreUndoUpdate = true; - if (scale.X > m_scene.m_maxNonphys) - scale.X = m_scene.m_maxNonphys; - if (scale.Y > m_scene.m_maxNonphys) - scale.Y = m_scene.m_maxNonphys; - if (scale.Z > m_scene.m_maxNonphys) - scale.Z = m_scene.m_maxNonphys; - if (part.PhysActor != null && part.PhysActor.IsPhysical) - { - if (scale.X > m_scene.m_maxPhys) - scale.X = m_scene.m_maxPhys; - if (scale.Y > m_scene.m_maxPhys) - scale.Y = m_scene.m_maxPhys; - if (scale.Z > m_scene.m_maxPhys) - scale.Z = m_scene.m_maxPhys; - } - float x = (scale.X / part.Scale.X); - float y = (scale.Y / part.Scale.Y); - float z = (scale.Z / part.Scale.Z); - - SceneObjectPart[] parts; - if (x > 1.0f || y > 1.0f || z > 1.0f) - { - parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart obPart = parts[i]; - if (obPart.UUID != m_rootPart.UUID) - { - obPart.IgnoreUndoUpdate = true; - Vector3 oldSize = new Vector3(obPart.Scale); - - float f = 1.0f; - float a = 1.0f; - - if (part.PhysActor != null && part.PhysActor.IsPhysical) - { - if (oldSize.X * x > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } - } - else - { - if (oldSize.X * x > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } - } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); - } - } - } - - Vector3 prevScale = part.Scale; - prevScale.X *= x; - prevScale.Y *= y; - prevScale.Z *= z; - part.Resize(prevScale); - parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; - obPart.IgnoreUndoUpdate = true; if (obPart.UUID != m_rootPart.UUID) { - Vector3 currentpos = new Vector3(obPart.OffsetPosition); - currentpos.X *= x; - currentpos.Y *= y; - currentpos.Z *= z; - Vector3 newSize = new Vector3(obPart.Scale); - newSize.X *= x; - newSize.Y *= y; - newSize.Z *= z; - obPart.Resize(newSize); - obPart.UpdateOffSet(currentpos); +// obPart.IgnoreUndoUpdate = true; + Vector3 oldSize = new Vector3(obPart.Scale); + + float f = 1.0f; + float a = 1.0f; + + if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical) + { + if (oldSize.X * x > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } + + if (oldSize.Y * y > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + + if (oldSize.Z * z > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } + } + else + { + if (oldSize.X * x > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } + + if (oldSize.Y * y > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + + if (oldSize.Z * z > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } + } + +// obPart.IgnoreUndoUpdate = false; } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); } - - if (part.PhysActor != null) - { - part.PhysActor.Size = prevScale; - m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); - } - - part.IgnoreUndoUpdate = false; - part.StoreUndoState(); - HasGroupChanged = true; - m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); - ScheduleGroupForTerseUpdate(); } + + Vector3 prevScale = RootPart.Scale; + prevScale.X *= x; + prevScale.Y *= y; + prevScale.Z *= z; + +// RootPart.IgnoreUndoUpdate = true; + RootPart.Resize(prevScale); +// RootPart.IgnoreUndoUpdate = false; + + parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart obPart = parts[i]; + + if (obPart.UUID != m_rootPart.UUID) + { + obPart.IgnoreUndoUpdate = true; + + Vector3 currentpos = new Vector3(obPart.OffsetPosition); + currentpos.X *= x; + currentpos.Y *= y; + currentpos.Z *= z; + + Vector3 newSize = new Vector3(obPart.Scale); + newSize.X *= x; + newSize.Y *= y; + newSize.Z *= z; + + obPart.Resize(newSize); + obPart.UpdateOffSet(currentpos); + + obPart.IgnoreUndoUpdate = false; + } + +// obPart.IgnoreUndoUpdate = false; +// obPart.StoreUndoState(); + } + +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale); } #endregion @@ -2809,9 +2772,13 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupPosition(Vector3 pos) { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); + + RootPart.StoreUndoState(true); + +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { @@ -2848,12 +2815,18 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectPart part = GetChildPart(localID); - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); if (part != null) { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); + + part.StoreUndoState(false); + part.IgnoreUndoUpdate = true; + if (part.UUID == m_rootPart.UUID) { UpdateRootPosition(pos); @@ -2864,18 +2837,22 @@ namespace OpenSim.Region.Framework.Scenes } HasGroupChanged = true; + part.IgnoreUndoUpdate = false; } } /// - /// + /// Update just the root prim position in a linkset /// /// - private void UpdateRootPosition(Vector3 pos) + public void UpdateRootPosition(Vector3 pos) { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos); + +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); Vector3 oldPos = @@ -2888,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes axDiff *= Quaternion.Inverse(partRotation); diff = axDiff; - parts = m_parts.GetArray(); + SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; @@ -2917,9 +2894,14 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationR(Quaternion rot) { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot); + +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); + + m_rootPart.StoreUndoState(true); m_rootPart.UpdateRotation(rot); @@ -2941,9 +2923,15 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot); + +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); + + RootPart.StoreUndoState(true); + RootPart.IgnoreUndoUpdate = true; m_rootPart.UpdateRotation(rot); @@ -2958,6 +2946,8 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; ScheduleGroupForTerseUpdate(); + + RootPart.IgnoreUndoUpdate = false; } /// @@ -2975,6 +2965,9 @@ namespace OpenSim.Region.Framework.Scenes if (part != null) { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); + if (part.UUID == m_rootPart.UUID) { UpdateRootRotation(rot); @@ -2996,6 +2989,13 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", +// part.Name, part.LocalId, rot); + + part.StoreUndoState(); + part.IgnoreUndoUpdate = true; + if (part.UUID == m_rootPart.UUID) { UpdateRootRotation(rot); @@ -3003,12 +3003,11 @@ namespace OpenSim.Region.Framework.Scenes } else { - part.IgnoreUndoUpdate = true; part.UpdateRotation(rot); part.OffsetPosition = pos; - part.IgnoreUndoUpdate = false; - part.StoreUndoState(); } + + part.IgnoreUndoUpdate = false; } } @@ -3016,8 +3015,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - private void UpdateRootRotation(Quaternion rot) + public void UpdateRootRotation(Quaternion rot) { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}", +// Name, LocalId, rot); + Quaternion axRot = rot; Quaternion oldParentRot = m_rootPart.RotationOffset; @@ -3045,20 +3048,25 @@ namespace OpenSim.Region.Framework.Scenes newRot *= Quaternion.Inverse(axRot); prim.RotationOffset = newRot; prim.ScheduleTerseUpdate(); + prim.IgnoreUndoUpdate = false; } } - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart childpart = parts[i]; - if (childpart != m_rootPart) - { - childpart.IgnoreUndoUpdate = false; - childpart.StoreUndoState(); - } - } +// for (int i = 0; i < parts.Length; i++) +// { +// SceneObjectPart childpart = parts[i]; +// if (childpart != m_rootPart) +// { +//// childpart.IgnoreUndoUpdate = false; +//// childpart.StoreUndoState(); +// } +// } m_rootPart.ScheduleTerseUpdate(); + +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", +// Name, LocalId, rot); } #endregion @@ -3312,23 +3320,6 @@ namespace OpenSim.Region.Framework.Scenes parts[i].CheckSculptAndLoad(); } - /// - /// Handle an asset received asynchronously from the asset service. - /// - /// - /// - /// - protected void AssetReceived(string id, Object sender, AssetBase asset) - { - SceneObjectPart sop = (SceneObjectPart)sender; - - if (sop != null) - { - if (asset != null) - sop.SculptTextureCallback(asset.FullID, asset); - } - } - /// /// Set the user group to which this scene object belongs. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2026c5357c..4629757de3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -287,8 +287,8 @@ namespace OpenSim.Region.Framework.Scenes private string m_sitAnimation = "SIT"; private string m_text = String.Empty; private string m_touchName = String.Empty; - private readonly UndoStack m_undo = new UndoStack(5); - private readonly UndoStack m_redo = new UndoStack(5); + private readonly Stack m_undo = new Stack(5); + private readonly Stack m_redo = new Stack(5); private UUID _creatorID; private bool m_passTouches; @@ -414,7 +414,6 @@ namespace OpenSim.Region.Framework.Scenes CreateSelected = true; TrimPermissions(); - //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); m_inventory = new SceneObjectPartInventory(this); } @@ -789,7 +788,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_offsetPosition; } set { - StoreUndoState(); +// StoreUndoState(); m_offsetPosition = value; if (ParentGroup != null && !ParentGroup.IsDeleted) @@ -1015,15 +1014,19 @@ namespace OpenSim.Region.Framework.Scenes get { return m_shape; } set { m_shape = value; } } - + + /// + /// Change the scale of this part. + /// public Vector3 Scale { get { return m_shape.Scale; } set { - StoreUndoState(); if (m_shape != null) { + StoreUndoState(); + m_shape.Scale = value; PhysicsActor actor = PhysActor; @@ -1034,11 +1037,16 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentGroup.Scene.PhysicsScene != null) { actor.Size = m_shape.Scale; - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); + + if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh) + CheckSculptAndLoad(); + else + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } } } } + TriggerScriptChangedEvent(Changed.SCALE); } } @@ -1588,17 +1596,23 @@ namespace OpenSim.Region.Framework.Scenes // or flexible if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) { -// m_log.DebugFormat("[SCENE OBJECT PART]: Creating PhysActor for {0} {1} {2}", Name, LocalId, UUID); - - PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( - LocalId, - string.Format("{0}/{1}", Name, UUID), - Shape, - AbsolutePosition, - Scale, - RotationOffset, - RigidBody); - + try + { + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + string.Format("{0}/{1}", Name, UUID), + Shape, + AbsolutePosition, + Scale, + RotationOffset, + RigidBody, + m_localId); + PhysActor.SetMaterial(Material); + } + catch + { + m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); + PhysActor = null; + } // Basic Physics returns null.. joy joy joy. if (PhysActor != null) { @@ -1615,19 +1629,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public void ClearUndoState() - { - lock (m_undo) - { - m_undo.Clear(); - } - lock (m_redo) - { - m_redo.Clear(); - } - StoreUndoState(); - } - public byte ConvertScriptUintToByte(uint indata) { byte outdata = (byte)TextureAnimFlags.NONE; @@ -1705,7 +1706,8 @@ namespace OpenSim.Region.Framework.Scenes { if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) { - m_parentGroup.Scene.AssetService.Get(dupe.m_shape.SculptTexture.ToString(), dupe, AssetReceived); + ParentGroup.Scene.AssetService.Get( + dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived); } bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); @@ -1719,14 +1721,20 @@ namespace OpenSim.Region.Framework.Scenes return dupe; } + /// + /// Called back by asynchronous asset fetch. + /// + /// ID of asset received + /// Register + /// protected void AssetReceived(string id, Object sender, AssetBase asset) { if (asset != null) - { - SceneObjectPart sop = (SceneObjectPart)sender; - if (sop != null) - sop.SculptTextureCallback(asset.FullID, asset); - } + SculptTextureCallback(asset); + else + m_log.WarnFormat( + "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", + Name, LocalId, id); } public static SceneObjectPart Create() @@ -1896,7 +1904,12 @@ namespace OpenSim.Region.Framework.Scenes } } - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + // If this part is a sculpt then delay the physics update until we've asynchronously loaded the + // mesh data. + if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh) + CheckSculptAndLoad(); + else + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } } } @@ -2823,19 +2836,29 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Resize this part. + /// Set the scale of this part. /// + /// + /// Unlike the scale property, this checks the new size against scene limits and schedules a full property + /// update to viewers. + /// /// public void Resize(Vector3 scale) { - StoreUndoState(); - m_shape.Scale = scale; + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); - // If we're a mesh/sculpt, then we need to tell the physics engine about our new size. To do this, we - // need to reinsert the sculpt data into the shape, since the physics engine deletes it when done to - // save memory - if (PhysActor != null) - CheckSculptAndLoad(); + if (PhysActor != null && PhysActor.IsPhysical) + { + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); + } + +// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); + + Scale = scale; ParentGroup.HasGroupChanged = true; ScheduleFullUpdate(); @@ -2965,7 +2988,11 @@ namespace OpenSim.Region.Framework.Scenes } } - public void SculptTextureCallback(UUID textureID, AssetBase texture) + /// + /// Set sculpt and mesh data, and tell the physics engine to process the change. + /// + /// The mesh itself. + public void SculptTextureCallback(AssetBase texture) { if (m_shape.SculptEntry) { @@ -2991,16 +3018,6 @@ namespace OpenSim.Region.Framework.Scenes } } -// /// -// /// -// /// -// /// -// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) -// { -// m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); -// } - - /// /// Send a full update to the client for the given part /// @@ -3647,6 +3664,11 @@ namespace OpenSim.Region.Framework.Scenes } public void StoreUndoState() + { + StoreUndoState(false); + } + + public void StoreUndoState(bool forGroup) { if (!Undoing) { @@ -3661,21 +3683,135 @@ namespace OpenSim.Region.Framework.Scenes UndoState last = m_undo.Peek(); if (last != null) { + // TODO: May need to fix for group comparison if (last.Compare(this)) + { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", +// Name, LocalId, m_undo.Count); + return; + } } } +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", +// Name, LocalId, forGroup, m_undo.Count); + if (m_parentGroup.GetSceneMaxUndo() > 0) { - UndoState nUndo = new UndoState(this); + UndoState nUndo = new UndoState(this, forGroup); m_undo.Push(nUndo); - } + if (m_redo.Count > 0) + m_redo.Clear(); + +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", +// Name, LocalId, forGroup, m_undo.Count); + } } } } +// else +// { +// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); +// } + } +// else +// { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); +// } + } + + /// + /// Return number of undos on the stack. Here temporarily pending a refactor. + /// + public int UndoCount + { + get + { + lock (m_undo) + return m_undo.Count; + } + } + + public void Undo() + { + lock (m_undo) + { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", +// Name, LocalId, m_undo.Count); + + if (m_undo.Count > 0) + { + UndoState goback = m_undo.Pop(); + + if (goback != null) + { + UndoState nUndo = null; + + if (m_parentGroup.GetSceneMaxUndo() > 0) + { + nUndo = new UndoState(this, goback.ForGroup); + } + + goback.PlaybackState(this); + + if (nUndo != null) + m_redo.Push(nUndo); + } + } + +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", +// Name, LocalId, m_undo.Count); + } + } + + public void Redo() + { + lock (m_undo) + { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", +// Name, LocalId, m_redo.Count); + + if (m_redo.Count > 0) + { + UndoState gofwd = m_redo.Pop(); + + if (gofwd != null) + { + if (m_parentGroup.GetSceneMaxUndo() > 0) + { + UndoState nUndo = new UndoState(this, gofwd.ForGroup); + + m_undo.Push(nUndo); + } + + gofwd.PlayfwdState(this); + } + +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", +// Name, LocalId, m_redo.Count); + } + } + } + + public void ClearUndoState() + { +// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); + + lock (m_undo) + { + m_undo.Clear(); + m_redo.Clear(); } } @@ -4139,44 +4275,6 @@ namespace OpenSim.Region.Framework.Scenes _nextOwnerMask &= (uint)PermissionMask.All; } - public void Undo() - { - lock (m_undo) - { - if (m_undo.Count > 0) - { - UndoState nUndo = null; - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - nUndo = new UndoState(this); - } - UndoState goback = m_undo.Pop(); - if (goback != null) - { - goback.PlaybackState(this); - if (nUndo != null) - m_redo.Push(nUndo); - } - } - } - } - - public void Redo() - { - lock (m_redo) - { - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this); - - m_undo.Push(nUndo); - } - UndoState gofwd = m_redo.Pop(); - if (gofwd != null) - gofwd.PlayfwdState(this); - } - } - public void UpdateExtraParam(ushort type, bool inUse, byte[] data) { m_shape.ReadInUpdateExtraParam(type, inUse, data); @@ -4435,13 +4533,14 @@ namespace OpenSim.Region.Framework.Scenes { // It's not phantom anymore. So make sure the physics engine get's knowledge of it PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( - LocalId, string.Format("{0}/{1}", Name, UUID), Shape, AbsolutePosition, Scale, RotationOffset, - UsePhysics); + UsePhysics, + m_localId); + PhysActor.SetMaterial(Material); pa = PhysActor; if (pa != null) @@ -4600,7 +4699,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void CheckSculptAndLoad() { -// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); +// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); if (ParentGroup.IsDeleted) return; @@ -4611,9 +4710,11 @@ namespace OpenSim.Region.Framework.Scenes if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero) { // check if a previously decoded sculpt map has been cached + // We don't read the file here - the meshmerizer will do that later. + // TODO: Could we simplify the meshmerizer code by reading and setting the data here? if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString()))) { - SculptTextureCallback(Shape.SculptTexture, null); + SculptTextureCallback(null); } else { diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index c18c93a771..8fb9fad831 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -102,7 +102,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sceneObject.AddPart(part); part.LinkNum = linkNum; part.TrimPermissions(); - part.StoreUndoState(); reader.Close(); sr.Close(); } @@ -236,15 +235,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization if (originalLinkNum != 0) part.LinkNum = originalLinkNum; - part.StoreUndoState(); reader.Close(); sr.Close(); } // Script state may, or may not, exist. Not having any, is NOT // ever a problem. - sceneObject.LoadScriptState(doc); + return sceneObject; } catch (Exception e) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs new file mode 100644 index 0000000000..c4047ee0cf --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs @@ -0,0 +1,104 @@ +/* + * 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.Reflection; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Basic scene object resize tests + /// + [TestFixture] + public class SceneObjectResizeTests + { + /// + /// Test resizing an object + /// + [Test] + public void TestResizeSceneObject() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + SceneObjectGroup g1 = SceneSetupHelpers.AddSceneObject(scene).ParentGroup; + + g1.GroupResize(new Vector3(2, 3, 4)); + + SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID); + + Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); + Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); + Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); + + Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1)); + } + + /// + /// Test resizing an individual part in a scene object. + /// + [Test] + public void TestResizeSceneObjectPart() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + + SceneObjectGroup g1 = SceneSetupHelpers.CreateSceneObject(2, UUID.Zero); + g1.RootPart.Scale = new Vector3(2, 3, 4); + g1.Parts[1].Scale = new Vector3(5, 6, 7); + + scene.AddSceneObject(g1); + + SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID); + + g1Post.Parts[1].Resize(new Vector3(8, 9, 10)); + + SceneObjectGroup g1PostPost = scene.GetSceneObjectGroup(g1.UUID); + + SceneObjectPart g1RootPart = g1PostPost.RootPart; + SceneObjectPart g1ChildPart = g1PostPost.Parts[1]; + + Assert.That(g1RootPart.Scale.X, Is.EqualTo(2)); + Assert.That(g1RootPart.Scale.Y, Is.EqualTo(3)); + Assert.That(g1RootPart.Scale.Z, Is.EqualTo(4)); + + Assert.That(g1ChildPart.Scale.X, Is.EqualTo(8)); + Assert.That(g1ChildPart.Scale.Y, Is.EqualTo(9)); + Assert.That(g1ChildPart.Scale.Z, Is.EqualTo(10)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 55e407ec5f..393f42d840 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -25,6 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; +using System.Reflection; +using log4net; using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; @@ -32,110 +35,199 @@ namespace OpenSim.Region.Framework.Scenes { public class UndoState { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public Vector3 Position = Vector3.Zero; public Vector3 Scale = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; - public UndoState(SceneObjectPart part) + /// + /// Is this undo state for an entire group? + /// + public bool ForGroup; + + /// + /// Constructor. + /// + /// + /// True if the undo is for an entire group + public UndoState(SceneObjectPart part, bool forGroup) { - if (part != null) + if (part.ParentID == 0) { - if (part.ParentID == 0) - { + ForGroup = forGroup; + +// if (ForGroup) Position = part.ParentGroup.AbsolutePosition; - Rotation = part.RotationOffset; - Scale = part.Shape.Scale; - } - else - { - Position = part.OffsetPosition; - Rotation = part.RotationOffset; - Scale = part.Shape.Scale; - } +// else +// Position = part.OffsetPosition; + +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo position {0} for root part", Position); + + Rotation = part.RotationOffset; + +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); + + Scale = part.Shape.Scale; + +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); + } + else + { + Position = part.OffsetPosition; +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo position {0} for child part", Position); + + Rotation = part.RotationOffset; +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); + + Scale = part.Shape.Scale; +// m_log.DebugFormat( +// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); } } + /// + /// Compare the relevant state in the given part to this state. + /// + /// + /// true if both the part's position, rotation and scale match those in this undo state. False otherwise. public bool Compare(SceneObjectPart part) { if (part != null) { if (part.ParentID == 0) - { - if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) - return true; - else - return false; - } + return + Position == part.ParentGroup.AbsolutePosition + && Rotation == part.RotationOffset + && Scale == part.Shape.Scale; else - { - if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) - return true; - else - return false; - - } + return + Position == part.OffsetPosition + && Rotation == part.RotationOffset + && Scale == part.Shape.Scale; } + return false; } public void PlaybackState(SceneObjectPart part) { - if (part != null) + part.Undoing = true; + + if (part.ParentID == 0) { - part.Undoing = true; +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", +// Position, part.Name, part.LocalId); - if (part.ParentID == 0) + if (Position != Vector3.Zero) { - if (Position != Vector3.Zero) + if (ForGroup) part.ParentGroup.AbsolutePosition = Position; - part.RotationOffset = Rotation; - if (Scale != Vector3.Zero) - part.Resize(Scale); - part.ParentGroup.ScheduleGroupForTerseUpdate(); + else + part.ParentGroup.UpdateRootPosition(Position); } - else - { - if (Position != Vector3.Zero) - part.OffsetPosition = Position; - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); part.ScheduleTerseUpdate(); - } - part.Undoing = false; +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", +// part.RotationOffset, Rotation, part.Name, part.LocalId); + + if (ForGroup) + part.UpdateRotation(Rotation); + else + part.ParentGroup.UpdateRootRotation(Rotation); + + if (Scale != Vector3.Zero) + { +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", +// part.Shape.Scale, Scale, part.Name, part.LocalId); + + if (ForGroup) + part.ParentGroup.GroupResize(Scale); + else + part.Resize(Scale); + } + + part.ParentGroup.ScheduleGroupForTerseUpdate(); } + else + { + if (Position != Vector3.Zero) + { +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", +// part.OffsetPosition, Position, part.Name, part.LocalId); + + part.OffsetPosition = Position; + } + +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", +// part.RotationOffset, Rotation, part.Name, part.LocalId); + + part.UpdateRotation(Rotation); + + if (Scale != Vector3.Zero) + { +// m_log.DebugFormat( +// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", +// part.Shape.Scale, Scale, part.Name, part.LocalId); + + part.Resize(Scale); + } + + part.ScheduleTerseUpdate(); + } + + part.Undoing = false; } + public void PlayfwdState(SceneObjectPart part) { - if (part != null) + part.Undoing = true; + + if (part.ParentID == 0) { - part.Undoing = true; + if (Position != Vector3.Zero) + part.ParentGroup.AbsolutePosition = Position; - if (part.ParentID == 0) - { - if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; - if (Rotation != Quaternion.Identity) - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); - part.ParentGroup.ScheduleGroupForTerseUpdate(); - } - else - { - if (Position != Vector3.Zero) - part.OffsetPosition = Position; - if (Rotation != Quaternion.Identity) - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); - part.ScheduleTerseUpdate(); - } - part.Undoing = false; + if (Rotation != Quaternion.Identity) + part.UpdateRotation(Rotation); + if (Scale != Vector3.Zero) + { + if (ForGroup) + part.ParentGroup.GroupResize(Scale); + else + part.Resize(Scale); + } + + part.ParentGroup.ScheduleGroupForTerseUpdate(); } + else + { + if (Position != Vector3.Zero) + part.OffsetPosition = Position; + + if (Rotation != Quaternion.Identity) + part.UpdateRotation(Rotation); + + if (Scale != Vector3.Zero) + part.Resize(Scale); + + part.ScheduleTerseUpdate(); + } + + part.Undoing = false; } } + public class LandUndoState { public ITerrainModule m_terrainModule; @@ -149,10 +241,7 @@ namespace OpenSim.Region.Framework.Scenes public bool Compare(ITerrainChannel terrainChannel) { - if (m_terrainChannel != terrainChannel) - return false; - else - return false; + return m_terrainChannel == terrainChannel; } public void PlaybackState() @@ -160,4 +249,4 @@ namespace OpenSim.Region.Framework.Scenes m_terrainModule.UndoTerrain(m_terrainChannel); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/MonitorServicesModule.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/MonitorServicesModule.cs new file mode 100644 index 0000000000..d49face7ad --- /dev/null +++ b/OpenSim/Region/OptionalModules/Framework/Monitoring/MonitorServicesModule.cs @@ -0,0 +1,119 @@ +/* + * 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.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Framework.Monitoring +{ + /// + /// An experimental module to return data on services used by the simulator. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MonitorServicesModule")] + public class MonitorServicesModule : ISharedRegionModule + { + protected Scene m_scene; + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public string Name { get { return "Services Health Monitoring Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public void AddRegion(Scene scene) + { + if (m_scene == null) + { + m_scene = scene; + +// m_scene.AddCommand(this, "monitor services", +// "monitor services", +// "Returns the status of services used by the simulator. Experimental.", +// HandleMonitorServices); + } + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + } + + protected void HandleMonitorServices(string module, string[] args) + { + MainConsole.Instance.Output(GenerateServicesReport()); + } + + protected string GenerateServicesReport() + { + StringBuilder sb = new StringBuilder(); + sb.Append("This is an experimental module. Please don't rely on these results\n"); + sb.Append("Asset service: "); + + try + { + CheckAssetService(); + sb.Append("OK"); + } + catch (Exception e) + { + sb.AppendFormat("FAIL ({0})", e.Message); + } + + return sb.ToString(); + } + + protected void CheckAssetService() + { + // Try to fetch an asset that will not exist (and hence avoid hitting cache) + m_scene.AssetService.Get(UUID.Random().ToString()); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs index d18ac0a90c..2187449471 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs @@ -106,7 +106,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule info.channel = channel; info.uri = uri; - bool success = SynchronousRestObjectPoster.BeginPostObject( + bool success = SynchronousRestObjectRequester.MakeRequest( "POST", m_ServerURI+"/RegisterChannel/", info); if (!success) @@ -125,7 +125,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule if (m_Channels.ContainsKey(itemID)) { - bool success = SynchronousRestObjectPoster.BeginPostObject( + bool success = SynchronousRestObjectRequester.MakeRequest( "POST", m_ServerURI+"/RemoveChannel/", m_Channels[itemID]); if (!success) diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs index b6e1cb465c..6c9d9aba1d 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs @@ -84,13 +84,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin */ public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) + Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { return null; } diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs index 6df213d851..0d1bd82741 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs @@ -213,12 +213,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin return newPrim; } - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation) - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical) + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { PhysicsActor result; IMesh mesh = null; diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index e2a6a2ed11..df62dbcab3 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -626,13 +626,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin } public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, OpenMetaverse.Vector3 position, - OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation) - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, OpenMetaverse.Vector3 position, - OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, bool isPhysical) + OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, bool isPhysical, uint localid) { PhysicsActor result; diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 13ea084978..3870411427 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -37,6 +37,18 @@ namespace OpenSim.Region.Physics.Manager public delegate void physicsCrash(); public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); + public delegate void RayCallback(List list); + + /// + /// Contact result from a raycast. + /// + public struct ContactResult + { + public Vector3 Pos; + public float Depth; + public uint ConsumerID; + public Vector3 Normal; + } public abstract class PhysicsScene { @@ -61,7 +73,6 @@ namespace OpenSim.Region.Physics.Manager } } - public abstract void Initialise(IMesher meshmerizer, IConfigSource config); public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); @@ -78,20 +89,7 @@ namespace OpenSim.Region.Physics.Manager public abstract void RemovePrim(PhysicsActor prim); public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation); //To be removed - public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical); - - public virtual PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) - { - PhysicsActor ret = AddPrimShape(primName, pbs, position, size, rotation, isPhysical); - - if (ret != null) - ret.LocalID = localID; - - return ret; - } + Vector3 size, Quaternion rotation, bool isPhysical, uint localid); public virtual float TimeDilation { @@ -225,6 +223,17 @@ namespace OpenSim.Region.Physics.Manager retMethod(false, Vector3.Zero, 0, 999999999999f, Vector3.Zero); } + public virtual void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) + { + if (retMethod != null) + retMethod(new List()); + } + + public virtual List RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) + { + return new List(); + } + private class NullPhysicsScene : PhysicsScene { private static int m_workIndicator; @@ -262,13 +271,7 @@ namespace OpenSim.Region.Physics.Manager */ public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) + Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddPrim({0},{1})", position, size); return PhysicsActor.Null; diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 5ca5f204e0..5413aa8bc7 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -303,6 +303,10 @@ namespace OpenSim.Region.Physics.Meshing private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) { +// m_log.DebugFormat( +// "[MESH]: Creating physics proxy for {0}, shape {1}", +// primName, (OpenMetaverse.SculptType)primShape.SculptType); + PrimMesh primMesh; PrimMesher.SculptMesh sculptMesh; @@ -668,7 +672,6 @@ namespace OpenSim.Region.Physics.Meshing // If this mesh has been created already, return it instead of creating another copy // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory - key = GetMeshKey(primShape, size, lod); if (m_uniqueMeshes.TryGetValue(key, out mesh)) return mesh; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 123c8ff24d..b3045bd8cb 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -638,7 +638,7 @@ namespace OpenSim.Region.Physics.OdePlugin float profileEnd; if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) - { + { taperX1 = _pbs.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; @@ -648,9 +648,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; - } + } else - { + { taperX = _pbs.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; @@ -660,9 +660,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; - - } - + } volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); @@ -846,7 +844,6 @@ namespace OpenSim.Region.Physics.OdePlugin return; } - // if (IsPhysical && Body == (IntPtr) 0) // { // Recreate the body @@ -859,7 +856,9 @@ namespace OpenSim.Region.Physics.OdePlugin public void ProcessTaints(float timestep) { -//Console.WriteLine("ProcessTaints for " + Name); +#if SPAM +Console.WriteLine("ZProcessTaints for " + Name); +#endif if (m_taintadd) { changeadd(timestep); @@ -1323,7 +1322,9 @@ namespace OpenSim.Region.Physics.OdePlugin public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) { -//Console.WriteLine("CreateGeom:"); +#if SPAM +Console.WriteLine("CreateGeom:"); +#endif if (_mesh != null) { setMesh(_parent_scene, _mesh); @@ -1944,7 +1945,6 @@ Console.WriteLine(" JointCreateFixed"); if (_parent_scene.needsMeshing(_pbs)) mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); - //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); #if SPAM Console.WriteLine("changesize 1"); #endif @@ -2056,8 +2056,8 @@ Console.WriteLine("changesize 2"); if (IsPhysical) meshlod = _parent_scene.MeshSculptphysicalLOD; - IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); // createmesh returns null when it doesn't mesh. + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); #if SPAM Console.WriteLine("changeshape needed meshing"); #endif @@ -2284,6 +2284,7 @@ Console.WriteLine("changeshape not need meshing"); if (value.IsFinite()) { _size = value; +// m_log.DebugFormat("[PHYSICS]: Set size on {0} to {1}", Name, value); } else { diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs index ba77daebae..6c2bdde353 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs @@ -45,10 +45,15 @@ namespace OpenSim.Region.Physics.OdePlugin public class ODERayCastRequestManager { /// - /// Pending Raycast Requests + /// Pending raycast requests /// protected List m_PendingRequests = new List(); + /// + /// Pending ray requests + /// + protected List m_PendingRayRequests = new List(); + /// /// Scene that created this object. /// @@ -95,6 +100,29 @@ namespace OpenSim.Region.Physics.OdePlugin } } + /// + /// Queues a raycast + /// + /// Origin of Ray + /// Ray normal + /// Ray length + /// + /// Return method to send the results + public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) + { + lock (m_PendingRequests) + { + ODERayRequest req = new ODERayRequest(); + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = count; + + m_PendingRayRequests.Add(req); + } + } + /// /// Process all queued raycast requests /// @@ -112,18 +140,26 @@ namespace OpenSim.Region.Physics.OdePlugin if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast RayCast(reqs[i]); // if there isn't anyone to send results } - /* - foreach (ODERayCastRequest req in m_PendingRequests) - { - if (req.callbackMethod != null) // quick optimization here, don't raycast - RayCast(req); // if there isn't anyone to send results to - - } - */ + m_PendingRequests.Clear(); } } + lock (m_PendingRayRequests) + { + if (m_PendingRayRequests.Count > 0) + { + ODERayRequest[] reqs = m_PendingRayRequests.ToArray(); + for (int i = 0; i < reqs.Length; i++) + { + if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast + RayCast(reqs[i]); // if there isn't anyone to send results + } + + m_PendingRayRequests.Clear(); + } + } + lock (m_contactResults) m_contactResults.Clear(); @@ -146,7 +182,6 @@ namespace OpenSim.Region.Physics.OdePlugin // Remove Ray d.GeomDestroy(ray); - // Define default results bool hitYN = false; uint hitConsumerID = 0; @@ -177,6 +212,31 @@ namespace OpenSim.Region.Physics.OdePlugin req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal); } + /// + /// Method that actually initiates the raycast + /// + /// + private void RayCast(ODERayRequest req) + { + // Create the ray + IntPtr ray = d.CreateRay(m_scene.space, req.length); + d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); + + // Collide test + d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback); + + // Remove Ray + d.GeomDestroy(ray); + + // Find closest contact and object. + lock (m_contactResults) + { + // Return results + if (req.callbackMethod != null) + req.callbackMethod(m_contactResults); + } + } + // This is the standard Near. Uses space AABBs to speed up detection. private void near(IntPtr space, IntPtr g1, IntPtr g2) { @@ -342,10 +402,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_contactResults.Add(collisionresult); } } - - } - } /// @@ -365,11 +422,12 @@ namespace OpenSim.Region.Physics.OdePlugin public RaycastCallback callbackMethod; } - public struct ContactResult + public struct ODERayRequest { - public Vector3 Pos; - public float Depth; - public uint ConsumerID; + public Vector3 Origin; public Vector3 Normal; + public int Count; + public float length; + public RayCallback callbackMethod; } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 99392cc5a2..a3074691fc 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -1677,7 +1677,7 @@ namespace OpenSim.Region.Physics.OdePlugin } private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical, uint localID) { Vector3 pos = position; Vector3 siz = size; @@ -1691,7 +1691,7 @@ namespace OpenSim.Region.Physics.OdePlugin lock (_prims) _prims.Add(newPrim); } - + newPrim.LocalID = localID; return newPrim; } @@ -1708,13 +1708,7 @@ namespace OpenSim.Region.Physics.OdePlugin } public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) + Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { #if SPAM m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); @@ -1723,22 +1717,23 @@ namespace OpenSim.Region.Physics.OdePlugin PhysicsActor result; IMesh mesh = null; - if (needsMeshing(pbs)) - { - try - { - mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); - } - catch(Exception e) - { - m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName); - m_log.Debug(e.ToString()); - mesh = null; - return null; - } - } + // Don't create the mesh here - wait until the mesh data is loaded from the asset store. +// if (needsMeshing(pbs)) +// { +// try +// { +// mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); +// } +// catch(Exception e) +// { +// m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName); +// m_log.Debug(e.ToString()); +// mesh = null; +// return null; +// } +// } - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localid); return result; } @@ -2590,7 +2585,9 @@ namespace OpenSim.Region.Physics.OdePlugin { if (!(_taintedPrimH.Contains(taintedprim))) { -//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName); +#if SPAM +Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); +#endif _taintedPrimH.Add(taintedprim); // HashSet for searching _taintedPrimL.Add(taintedprim); // List for ordered readout } @@ -3733,6 +3730,34 @@ namespace OpenSim.Region.Physics.OdePlugin } } + public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) + { + if (retMethod != null) + { + m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); + } + } + + public override List RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) + { + ContactResult[] ourResults = null; + RayCallback retMethod = delegate(List results) + { + ourResults = new ContactResult[results.Count]; + results.CopyTo(ourResults, 0); + }; + int waitTime = 0; + m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); + while (ourResults == null && waitTime < 1000) + { + Thread.Sleep(1); + waitTime++; + } + if (ourResults == null) + return new List (); + return new List(ourResults); + } + #if USE_DRAWSTUFF // Keyboard callback public void command(int cmd) diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs index a7f8baa729..2ea810f997 100644 --- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs +++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs @@ -31,17 +31,18 @@ using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.OdePlugin; using log4net; using System.Reflection; -namespace OpenSim.Region.Physics.OdePlugin +namespace OpenSim.Region.Physics.OdePlugin.Tests { [TestFixture] public class ODETestClass { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private OdePlugin cbt; + private OpenSim.Region.Physics.OdePlugin.OdePlugin cbt; private PhysicsScene ps; private IMeshingPlugin imp; @@ -83,7 +84,7 @@ namespace OpenSim.Region.Physics.OdePlugin Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f); Vector3 size = new Vector3(0.5f, 0.5f, 0.5f); Quaternion rot = Quaternion.Identity; - PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true); + PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true, 0); OdePrim oprim = (OdePrim)prim; OdeScene pscene = (OdeScene) ps; diff --git a/OpenSim/Region/Physics/POSPlugin/POSScene.cs b/OpenSim/Region/Physics/POSPlugin/POSScene.cs index c3f5040842..2f24a50ea5 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSScene.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSScene.cs @@ -91,13 +91,7 @@ namespace OpenSim.Region.Physics.POSPlugin */ public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) + Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { POSPrim prim = new POSPrim(); prim.Position = position; diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXScene.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXScene.cs index 4de4b01482..beb340412f 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXScene.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXScene.cs @@ -108,13 +108,7 @@ namespace OpenSim.Region.Physics.PhysXPlugin } public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) + Vector3 size, Quaternion rotation, bool isPhysical, uint localid) { return AddPrim(position, size, rotation); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fd6d64c498..26969a550b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2214,7 +2214,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetVel() { m_host.AddScriptLPS(1); - return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); + + Vector3 vel; + + if (m_host.IsAttachment) + { + ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.AttachedAvatar); + vel = avatar.Velocity; + } + else + { + vel = m_host.Velocity; + } + + return new LSL_Vector(vel.X, vel.Y, vel.Z); } public LSL_Vector llGetAccel() @@ -2510,10 +2523,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// negative (indicating end-relative) and may be inverted, /// i.e. end < start. /// - public LSL_String llDeleteSubString(string src, int start, int end) { - m_host.AddScriptLPS(1); // Normalize indices (if negative). @@ -2593,10 +2604,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// which case it is end-relative. The index may exceed either /// string bound, with the result being a concatenation. /// - public LSL_String llInsertString(string dest, int index, string src) { - m_host.AddScriptLPS(1); // Normalize indices (if negative). @@ -9983,6 +9992,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetObjectDetails(string id, LSL_List args) { m_host.AddScriptLPS(1); + LSL_List ret = new LSL_List(); UUID key = new UUID(); if (UUID.TryParse(id, out key)) @@ -9993,72 +10003,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (object o in args.Data) { - switch (o.ToString()) + switch (int.Parse(o.ToString())) { - case "1": + case ScriptBaseClass.OBJECT_NAME: ret.Add(new LSL_String(av.Firstname + " " + av.Lastname)); break; - case "2": + case ScriptBaseClass.OBJECT_DESC: ret.Add(new LSL_String("")); break; - case "3": + case ScriptBaseClass.OBJECT_POS: ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); break; - case "4": + case ScriptBaseClass.OBJECT_ROT: ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); break; - case "5": + case ScriptBaseClass.OBJECT_VELOCITY: ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); break; - case "6": + case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(id)); break; - case "7": + case ScriptBaseClass.OBJECT_GROUP: ret.Add(new LSL_String(UUID.Zero.ToString())); break; - case "8": + case ScriptBaseClass.OBJECT_CREATOR: ret.Add(new LSL_String(UUID.Zero.ToString())); break; } } + return ret; } + SceneObjectPart obj = World.GetSceneObjectPart(key); if (obj != null) { foreach (object o in args.Data) { - switch (o.ToString()) + switch (int.Parse(o.ToString())) { - case "1": + case ScriptBaseClass.OBJECT_NAME: ret.Add(new LSL_String(obj.Name)); break; - case "2": + case ScriptBaseClass.OBJECT_DESC: ret.Add(new LSL_String(obj.Description)); break; - case "3": + case ScriptBaseClass.OBJECT_POS: ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); break; - case "4": + case ScriptBaseClass.OBJECT_ROT: ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); break; - case "5": + case ScriptBaseClass.OBJECT_VELOCITY: ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); break; - case "6": + case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); break; - case "7": + case ScriptBaseClass.OBJECT_GROUP: ret.Add(new LSL_String(obj.GroupID.ToString())); break; - case "8": + case ScriptBaseClass.OBJECT_CREATOR: ret.Add(new LSL_String(obj.CreatorID.ToString())); break; } } + return ret; } } + return new LSL_List(); } @@ -10309,51 +10323,191 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return rq.ToString(); } + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + { + m_host.AddScriptLPS(1); + + Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); + Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); + Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); + + int count = 0; +// int detectPhantom = 0; + int dataFlags = 0; + int rejectTypes = 0; + + for (int i = 0; i < options.Length; i += 2) + { + if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) + { + count = options.GetLSLIntegerItem(i + 1); + } +// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) +// { +// detectPhantom = options.GetLSLIntegerItem(i + 1); +// } + else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) + { + dataFlags = options.GetLSLIntegerItem(i + 1); + } + else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) + { + rejectTypes = options.GetLSLIntegerItem(i + 1); + } + } + + LSL_List list = new LSL_List(); + List results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); + + double distance = Util.GetDistanceTo(startvector, endvector); + + if (distance == 0) + distance = 0.001; + + Vector3 posToCheck = startvector; + ITerrainChannel channel = World.RequestModuleInterface(); + + bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); + bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); + bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); + bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); + + for (float i = 0; i <= distance; i += 0.1f) + { + posToCheck = startvector + (dir * (i / (float)distance)); + + if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) + { + ContactResult result = new ContactResult(); + result.ConsumerID = 0; + result.Depth = 0; + result.Normal = Vector3.Zero; + result.Pos = posToCheck; + results.Add(result); + checkTerrain = false; + } + + if (checkAgents) + { + World.ForEachScenePresence(delegate(ScenePresence sp) + { + if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) + { + ContactResult result = new ContactResult (); + result.ConsumerID = sp.LocalId; + result.Depth = 0; + result.Normal = Vector3.Zero; + result.Pos = posToCheck; + results.Add(result); + } + }); + } + } + + int refcount = 0; + foreach (ContactResult result in results) + { + if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) + == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) + continue; + + ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); + + if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) + entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents + + if (entity == null) + { + list.Add(UUID.Zero); + + if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) + list.Add(0); + + list.Add(result.Pos); + + if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) + list.Add(result.Normal); + + continue; //Can't find it, so add UUID.Zero + } + + /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && + ((ISceneChildEntity)intersection.obj).PhysActor == null) + continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects + + if (entity is SceneObjectPart) + { + if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) + { + if (!checkPhysical) + continue; + } + else + { + if (!checkNonPhysical) + continue; + } + } + + refcount++; + if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) + list.Add(((SceneObjectPart)entity).ParentGroup.UUID); + else + list.Add(entity.UUID); + + if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) + { + if (entity is SceneObjectPart) + list.Add(((SceneObjectPart)entity).LinkNum); + else + list.Add(0); + } + + list.Add(result.Pos); + + if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) + list.Add(result.Normal); + } + + list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED + + return list; + } + #region Not Implemented // // Listing the unimplemented lsl functions here, please move // them from this region as they are completed // - public void llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) - { - m_host.AddScriptLPS(1); - NotImplemented("llCastRay"); - - } public void llGetEnv(LSL_String name) { m_host.AddScriptLPS(1); NotImplemented("llGetEnv"); - } public void llGetSPMaxMemory() { m_host.AddScriptLPS(1); NotImplemented("llGetSPMaxMemory"); - } public void llGetUsedMemory() { m_host.AddScriptLPS(1); NotImplemented("llGetUsedMemory"); - } - public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg ) + public void llRegionSayTo(LSL_Key target, LSL_Integer channel, LSL_String msg) { m_host.AddScriptLPS(1); NotImplemented("llRegionSayTo"); - } - public void llScriptProfiler( LSL_Integer flags ) + public void llScriptProfiler(LSL_Integer flags) { m_host.AddScriptLPS(1); NotImplemented("llScriptProfiler"); - } public void llSetSoundQueueing(int queue) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 654ea8129a..27f9c84611 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -60,6 +60,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_String llBase64ToString(string str); void llBreakAllLinks(); void llBreakLink(int linknum); + LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options); LSL_Integer llCeil(double f); void llClearCameraParams(); LSL_Integer llClearPrimMedia(LSL_Integer face); @@ -404,7 +405,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_String llXorBase64StringsCorrect(string str1, string str2); void print(string str); - void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); - LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 9377cdafd8..3f90788433 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -593,5 +593,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const string URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED"; public const string URL_REQUEST_DENIED = "URL_REQUEST_DENIED"; + + public static readonly LSLInteger RC_REJECT_TYPES = 2; + public static readonly LSLInteger RC_DATA_FLAGS = 4; + public static readonly LSLInteger RC_MAX_HITS = 8; + public static readonly LSLInteger RC_DETECT_PHANTOM = 16; + + public static readonly LSLInteger RC_REJECT_AGENTS = 2; + public static readonly LSLInteger RC_REJECT_PHYSICAL = 4; + public static readonly LSLInteger RC_REJECT_NONPHYSICAL = 8; + public static readonly LSLInteger RC_REJECT_LAND = 16; + + public static readonly LSLInteger RC_GET_NORMAL = 2; + public static readonly LSLInteger RC_GET_ROOT_KEY = 4; + public static readonly LSLInteger RC_GET_LINK_NUM = 8; + + public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 1; } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 6265bcd3fc..08a3876676 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -244,6 +244,7 @@ namespace OpenSim.Services.Connectors.Hypergrid { m_log.Debug("[USER AGENT CONNECTOR]: PackAgentCircuitData failed with exception: " + e.Message); } + // Add the input arguments args["gatekeeper_serveruri"] = OSD.FromString(gatekeeper.ServerURI); args["gatekeeper_host"] = OSD.FromString(gatekeeper.ExternalHostName); @@ -429,7 +430,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList); - string reason = string.Empty; +// string reason = string.Empty; // Send and get reply List friendsOnline = new List(); @@ -438,17 +439,17 @@ namespace OpenSim.Services.Connectors.Hypergrid { response = request.Send(m_ServerURL, 6000); } - catch (Exception e) + catch { m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; return friendsOnline; } if (response.IsFault) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); - reason = "XMLRPC Fault"; +// reason = "XMLRPC Fault"; return friendsOnline; } @@ -460,7 +461,7 @@ namespace OpenSim.Services.Connectors.Hypergrid if (hash == null) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - reason = "Internal error 1"; +// reason = "Internal error 1"; return friendsOnline; } @@ -476,10 +477,10 @@ namespace OpenSim.Services.Connectors.Hypergrid } } - catch (Exception e) + catch { m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; } return friendsOnline; @@ -500,7 +501,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList); - string reason = string.Empty; +// string reason = string.Empty; // Send and get reply List online = new List(); @@ -509,17 +510,17 @@ namespace OpenSim.Services.Connectors.Hypergrid { response = request.Send(m_ServerURL, 10000); } - catch (Exception e) + catch { m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; return online; } if (response.IsFault) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); - reason = "XMLRPC Fault"; +// reason = "XMLRPC Fault"; return online; } @@ -531,7 +532,7 @@ namespace OpenSim.Services.Connectors.Hypergrid if (hash == null) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - reason = "Internal error 1"; +// reason = "Internal error 1"; return online; } @@ -547,10 +548,10 @@ namespace OpenSim.Services.Connectors.Hypergrid } } - catch (Exception e) + catch { m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; } return online; @@ -565,7 +566,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList); - string reason = string.Empty; +// string reason = string.Empty; // Send and get reply Dictionary serverURLs = new Dictionary(); @@ -574,17 +575,17 @@ namespace OpenSim.Services.Connectors.Hypergrid { response = request.Send(m_ServerURL, 10000); } - catch (Exception e) + catch { m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; return serverURLs; } if (response.IsFault) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); - reason = "XMLRPC Fault"; +// reason = "XMLRPC Fault"; return serverURLs; } @@ -596,7 +597,7 @@ namespace OpenSim.Services.Connectors.Hypergrid if (hash == null) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - reason = "Internal error 1"; +// reason = "Internal error 1"; return serverURLs; } @@ -611,10 +612,10 @@ namespace OpenSim.Services.Connectors.Hypergrid } } - catch (Exception e) + catch { m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; } return serverURLs; @@ -629,7 +630,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList); - string reason = string.Empty; +// string reason = string.Empty; // Send and get reply string url = string.Empty; @@ -638,17 +639,17 @@ namespace OpenSim.Services.Connectors.Hypergrid { response = request.Send(m_ServerURL, 10000); } - catch (Exception e) + catch { m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; return url; } if (response.IsFault) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); - reason = "XMLRPC Fault"; +// reason = "XMLRPC Fault"; return url; } @@ -660,7 +661,7 @@ namespace OpenSim.Services.Connectors.Hypergrid if (hash == null) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - reason = "Internal error 1"; +// reason = "Internal error 1"; return url; } @@ -669,10 +670,10 @@ namespace OpenSim.Services.Connectors.Hypergrid url = hash["URL"].ToString(); } - catch (Exception e) + catch { m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; } return url; @@ -688,7 +689,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList); - string reason = string.Empty; +// string reason = string.Empty; // Send and get reply string uui = string.Empty; @@ -697,17 +698,17 @@ namespace OpenSim.Services.Connectors.Hypergrid { response = request.Send(m_ServerURL, 10000); } - catch (Exception e) + catch { m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; return uui; } if (response.IsFault) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); - reason = "XMLRPC Fault"; +// reason = "XMLRPC Fault"; return uui; } @@ -719,7 +720,7 @@ namespace OpenSim.Services.Connectors.Hypergrid if (hash == null) { m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - reason = "Internal error 1"; +// reason = "Internal error 1"; return uui; } @@ -728,10 +729,10 @@ namespace OpenSim.Services.Connectors.Hypergrid uui = hash["UUI"].ToString(); } - catch (Exception e) + catch { m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); - reason = "Exception: " + e.Message; +// reason = "Exception: " + e.Message; } return uui; diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs index 520d639ccf..69e2d17949 100644 --- a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -50,7 +50,6 @@ namespace OpenSim.Services.Connectors MethodBase.GetCurrentMethod().DeclaringType); private string m_ServerURI = String.Empty; - private IImprovedAssetCache m_Cache = null; public MapImageServicesConnector() { diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index ded589de2d..bb31fc951e 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -326,7 +326,6 @@ namespace OpenSim.Services.HypergridService // This is recursive!!!!! return TrySendInstantMessage(im, url, false, foreigner); } - } private bool UndeliveredMessage(GridInstantMessage im) @@ -335,15 +334,14 @@ namespace OpenSim.Services.HypergridService && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) { m_log.DebugFormat("[HG IM SERVICE]: Message saved"); - return SynchronousRestObjectPoster.BeginPostObject( + + return SynchronousRestObjectRequester.MakeRequest( "POST", m_RestURL + "/SaveMessage/", im); - } - else { return false; } } } -} +} \ No newline at end of file diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 4eb6fcf333..4e340592a6 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -28,19 +28,19 @@ AssetLoaderArgs = "assets/AssetSets.xml" ; - ; change this to your grid-wide asset server + ; Change this to your grid-wide asset server. Do not add a slash to the end of any of these addresses. ; AssetServerURI = "http://myassetserver.com:8003" [InventoryService] ; - ; change this to your grid-wide inventory server + ; Change this to your grid-wide inventory server ; InventoryServerURI = "http://myinventoryserver.com:8003" [GridService] ; - ; change this to your grid-wide grid server + ; Change this to your grid-wide grid server ; GridServerURI = "http://mygridserver.com:8003" ;AllowHypergridMapSearch = true @@ -49,51 +49,51 @@ ; MapTileDirectory = "./maptiles" ; === HG ONLY === - ;; change this to the address of your Gatekeeper service - ;; (usually bundled with the rest of the services in one - ;; Robust server in port 8002, but not always) - Gatekeeper="http://mygridserver.com:8002" + ;; Change this to the address of your Gatekeeper service + ;; (usually bundled with the rest of the services in one + ;; Robust server in port 8002, but not always) + Gatekeeper="http://mygridserver.com:8002" [Messaging] ; === HG ONLY === - ;; change this to the address of your Gatekeeper service + ;; Change this to the address of your Gatekeeper service ;; (usually bundled with the rest of the services in one ;; Robust server in port 8002, but not always) Gatekeeper = "http://mygridserver.com:8002" [AvatarService] ; - ; change this to your grid-wide grid server + ; Change this to your grid-wide grid server ; AvatarServerURI = "http://mygridserver.com:8003" [PresenceService] ; - ; change this to your grid-wide presence server + ; Change this to your grid-wide presence server ; PresenceServerURI = "http://mygridserver.com:8003" [UserAccountService] ; - ; change this to your grid-wide user accounts server + ; Change this to your grid-wide user accounts server ; UserAccountServerURI = "http://mygridserver.com:8003" [GridUserService] ; - ; change this to your grid-wide user accounts server + ; Change this to your grid-wide user accounts server ; GridUserServerURI = "http://mygridserver.com:8003" [AuthenticationService] ; - ; change this to your grid-wide authentication server + ; Change this to your grid-wide authentication server ; AuthenticationServerURI = "http://mygridserver.com:8003" [FriendsService] ; - ; change this to your grid-wide friends server + ; Change this to your grid-wide friends server ; FriendsServerURI = "http://mygridserver.com:8003" @@ -104,10 +104,10 @@ ; accessible from other grids ; ProfileServerURI = "http://mygridserver.com:8002/user" - Gatekeeper = "http://mygridserver.com:8002" - ;; If you want to protect your assets from being copied by foreign visitors - ;; uncomment the next line. You may want to do this on sims that have licensed content. - ; OutboundPermission = False + Gatekeeper = "http://mygridserver.com:8002" + ;; If you want to protect your assets from being copied by foreign visitors + ;; uncomment the next line. You may want to do this on sims that have licensed content. + ; OutboundPermission = False [UserAgentService] ; diff --git a/prebuild.xml b/prebuild.xml index 63590c85b7..53cb30cff3 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -3224,29 +3224,30 @@ TODO: this is kind of lame, we basically build a duplicate assembly but with tests added in, just because we can't resolve cross-bin-dir-refs. --> - + - ../../../../bin/ + ../../../../../bin/ - ../../../../bin/ + ../../../../../bin/ - ../../../../bin/ + ../../../../../bin/ - - + + - - - + + + +