private uint ComputeAngleDistancePriority(ScenePresence presence, ISceneEntity entity) { // And convert the distance to a priority queue, this computation gives queues // at 10, 20, 40, 80, 160, 320, 640, and 1280m // uint minpqueue = PriorityQueue.NumberOfImmediateQueues; uint maxqueue = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues - 1; // uint pqueue = minpqueue; uint pqueue = PriorityQueue.NumberOfImmediateQueues; float distance; Vector3 presencePos = presence.AbsolutePosition; if (entity is ScenePresence) { ScenePresence sp = entity as ScenePresence; distance = Vector3.Distance(presencePos, sp.AbsolutePosition); distance *= 0.5f; } else { SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; float bradius = group.GetBoundsRadius(); Vector3 grppos = group.AbsolutePosition + group.getBoundsCenter(); distance = Vector3.Distance(presencePos, grppos); distance -= bradius; distance *= group.getAreaFactor(); if (group.IsAttachment) { distance *= 0.5f; } else if (group.UsesPhysics) { distance *= 0.6f; } else if (group.GetSittingAvatarsCount() > 0) { distance *= 0.5f; } } if (distance > 10f) { float tmp = (float)Math.Log(distance) * 1.442695f - 3.321928f; // for a map identical to original: // now // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) // 2st constant makes it be log2(distance/10) pqueue += (uint)tmp; if (pqueue > maxqueue) { pqueue = maxqueue; } } return(pqueue); }
/// <summary> /// Internal method which actually does all the work for attaching an object. /// </summary> /// <returns>The object attached.</returns> /// <param name='sp'></param> /// <param name='group'>The object to attach.</param> /// <param name='attachmentPt'></param> /// <param name='silent'></param> /// <param name='addToInventory'>If true then add object to user inventory.</param> /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> /// <param name='append'>Append to attachment point rather than replace.</param> private bool AttachObjectInternal( IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append) { if (group.GetSittingAvatarsCount() != 0) { if (DebugLevel > 0) m_log.WarnFormat( "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); return false; } Vector3 attachPos = group.AbsolutePosition; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint) { attachPos = Vector3.Zero; } // if the attachment point is the same as previous, make sure we get the saved // position info. if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint) { attachPos = group.RootPart.AttachedPos; } // AttachmentPt 0 means the client chose to 'wear' the attachment. if (attachmentPt == (uint)AttachmentPoint.Default) { // Check object for stored attachment point attachmentPt = group.AttachmentPoint; } // if we didn't find an attach point, look for where it was last attached if (attachmentPt == 0) { attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; attachPos = group.RootPart.AttachedPos; group.HasGroupChanged = true; } // if we still didn't find a suitable attachment point....... if (attachmentPt == 0) { // Stick it on left hand with Zero Offset from the attachment point. attachmentPt = (uint)AttachmentPoint.LeftHand; attachPos = Vector3.Zero; } group.AttachmentPoint = attachmentPt; group.AbsolutePosition = attachPos; List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); if (attachments.Contains(group)) { if (DebugLevel > 0) m_log.WarnFormat( "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", group.Name, group.LocalId, sp.Name, attachmentPt); return false; } // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones while (attachments.Count >= 5) { if (attachments[0].FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, attachments[0]); attachments.RemoveAt(0); } // If we're not appending, remove the rest as well if (attachments.Count != 0 && !append) { foreach (SceneObjectGroup g in attachments) { if (g.FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, g); } } lock (sp.AttachmentsSyncLock) { if (addToInventory && sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); AttachToAgent(sp, group, attachmentPt, attachPos, silent); if (resumeScripts) { // Fire after attach, so we don't get messy perms dialogs // 4 == AttachedRez group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); group.ResumeScripts(); } // Do this last so that event listeners have access to all the effects of the attachment m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); } return true; }
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) { lock (sp.AttachmentsSyncLock) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", // group.Name, group.LocalId, sp.Name, attachmentPt, silent); if (group.GetSittingAvatarsCount() != 0) { // m_log.WarnFormat( // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", // group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); return false; } if (sp.GetAttachments(attachmentPt).Contains(group)) { // m_log.WarnFormat( // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", // group.Name, group.LocalId, sp.Name, AttachmentPt); return false; } Vector3 attachPos = group.AbsolutePosition; // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // be removed when that functionality is implemented in opensim attachmentPt &= 0x7f; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) { attachPos = Vector3.Zero; } // AttachmentPt 0 means the client chose to 'wear' the attachment. if (attachmentPt == 0) { // Check object for stored attachment point attachmentPt = group.AttachmentPoint; } // if we still didn't find a suitable attachment point....... if (attachmentPt == 0) { // Stick it on left hand with Zero Offset from the attachment point. attachmentPt = (uint)AttachmentPoint.LeftHand; attachPos = Vector3.Zero; } group.AttachmentPoint = attachmentPt; group.AbsolutePosition = attachPos; if (sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); AttachToAgent(sp, group, attachmentPt, attachPos, silent); } return true; }
private int ComputeAngleDistancePriority(ScenePresence presence, ISceneEntity entity) { int pqueue = PriorityQueue.NumberOfImmediateQueues; float distance; Vector3 presencePos = presence.AbsolutePosition; if (entity is ScenePresence) { ScenePresence sp = entity as ScenePresence; distance = Vector3.DistanceSquared(presencePos, sp.AbsolutePosition); if (distance > 400f) { float tmp = (float)Math.Log(distance) * 0.7213475f - 4.321928f; pqueue += (int)tmp; } return(pqueue); } SceneObjectPart sop = entity as SceneObjectPart; SceneObjectGroup group = sop.ParentGroup; if (presence.ParentPart != null) { if (presence.ParentPart.ParentGroup == group) { return(pqueue); } } if (group.IsAttachment) { if (group.RootPart.LocalId == presence.LocalId) { return(pqueue); } distance = Vector3.DistanceSquared(presencePos, group.AbsolutePosition); if (distance > 400f) { float tmp = (float)Math.Log(distance) * 0.7213475f - 4.321928f; pqueue += (int)tmp; } return(pqueue); } float bradius = group.GetBoundsRadius(); Vector3 grppos = group.getCenterOffset(); distance = Vector3.Distance(presencePos, grppos); distance -= bradius; if (distance < 0) { return(pqueue); } distance *= group.getAreaFactor(); if (group.IsAttachment) { distance *= 0.5f; } else if (group.UsesPhysics) { distance *= 0.6f; } else if (group.GetSittingAvatarsCount() > 0) { distance *= 0.5f; } if (distance > 10f) { float tmp = (float)Math.Log(distance) * 1.442695f - 3.321928f; // for a map identical to original: // now // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) // 2st constant makes it be log2(distance/10) pqueue += (int)tmp; } return(pqueue); }