diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 228 |
1 files changed, 170 insertions, 58 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 82ded28..e1fde64 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
43 | 43 | ||
44 | public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); | 44 | public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); |
45 | 45 | ||
46 | public delegate void AttachToBackupDelegate(SceneObjectGroup sog); | ||
47 | |||
48 | public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); | ||
49 | |||
50 | public delegate void ChangedBackupDelegate(SceneObjectGroup sog); | ||
51 | |||
46 | public delegate void ObjectCreateDelegate(EntityBase obj); | 52 | public delegate void ObjectCreateDelegate(EntityBase obj); |
47 | 53 | ||
48 | public delegate void ObjectDeleteDelegate(EntityBase obj); | 54 | public delegate void ObjectDeleteDelegate(EntityBase obj); |
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
61 | private PhysicsCrash handlerPhysicsCrash = null; | 67 | private PhysicsCrash handlerPhysicsCrash = null; |
62 | 68 | ||
63 | public event ObjectDuplicateDelegate OnObjectDuplicate; | 69 | public event ObjectDuplicateDelegate OnObjectDuplicate; |
70 | public event AttachToBackupDelegate OnAttachToBackup; | ||
71 | public event DetachFromBackupDelegate OnDetachFromBackup; | ||
72 | public event ChangedBackupDelegate OnChangeBackup; | ||
64 | public event ObjectCreateDelegate OnObjectCreate; | 73 | public event ObjectCreateDelegate OnObjectCreate; |
65 | public event ObjectDeleteDelegate OnObjectRemove; | 74 | public event ObjectDeleteDelegate OnObjectRemove; |
66 | 75 | ||
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
68 | 77 | ||
69 | #region Fields | 78 | #region Fields |
70 | 79 | ||
71 | protected object m_presenceLock = new object(); | 80 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); |
72 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); | 81 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); |
73 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); | 82 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); |
74 | 83 | ||
@@ -130,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
130 | 139 | ||
131 | protected internal void Close() | 140 | protected internal void Close() |
132 | { | 141 | { |
133 | lock (m_presenceLock) | 142 | m_scenePresencesLock.EnterWriteLock(); |
143 | try | ||
134 | { | 144 | { |
135 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 145 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
136 | List<ScenePresence> newlist = new List<ScenePresence>(); | 146 | List<ScenePresence> newlist = new List<ScenePresence>(); |
137 | m_scenePresenceMap = newmap; | 147 | m_scenePresenceMap = newmap; |
138 | m_scenePresenceArray = newlist; | 148 | m_scenePresenceArray = newlist; |
139 | } | 149 | } |
150 | finally | ||
151 | { | ||
152 | m_scenePresencesLock.ExitWriteLock(); | ||
153 | } | ||
140 | 154 | ||
141 | lock (SceneObjectGroupsByFullID) | 155 | lock (SceneObjectGroupsByFullID) |
142 | SceneObjectGroupsByFullID.Clear(); | 156 | SceneObjectGroupsByFullID.Clear(); |
@@ -275,6 +289,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
275 | protected internal bool AddRestoredSceneObject( | 289 | protected internal bool AddRestoredSceneObject( |
276 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 290 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
277 | { | 291 | { |
292 | if (!m_parentScene.CombineRegions) | ||
293 | { | ||
294 | // KF: Check for out-of-region, move inside and make static. | ||
295 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
296 | sceneObject.RootPart.GroupPosition.Y, | ||
297 | sceneObject.RootPart.GroupPosition.Z); | ||
298 | if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || | ||
299 | npos.X > Constants.RegionSize || | ||
300 | npos.Y > Constants.RegionSize)) | ||
301 | { | ||
302 | if (npos.X < 0.0) npos.X = 1.0f; | ||
303 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
304 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
305 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
306 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
307 | |||
308 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
309 | { | ||
310 | part.GroupPosition = npos; | ||
311 | } | ||
312 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
313 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
314 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
315 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
316 | } | ||
317 | } | ||
318 | |||
278 | if (attachToBackup && (!alreadyPersisted)) | 319 | if (attachToBackup && (!alreadyPersisted)) |
279 | { | 320 | { |
280 | sceneObject.ForceInventoryPersistence(); | 321 | sceneObject.ForceInventoryPersistence(); |
@@ -492,6 +533,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
492 | m_updateList[obj.UUID] = obj; | 533 | m_updateList[obj.UUID] = obj; |
493 | } | 534 | } |
494 | 535 | ||
536 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
537 | { | ||
538 | if (OnAttachToBackup != null) | ||
539 | { | ||
540 | OnAttachToBackup(obj); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
545 | { | ||
546 | if (OnDetachFromBackup != null) | ||
547 | { | ||
548 | OnDetachFromBackup(obj); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | public void FireChangeBackup(SceneObjectGroup obj) | ||
553 | { | ||
554 | if (OnChangeBackup != null) | ||
555 | { | ||
556 | OnChangeBackup(obj); | ||
557 | } | ||
558 | } | ||
559 | |||
495 | /// <summary> | 560 | /// <summary> |
496 | /// Process all pending updates | 561 | /// Process all pending updates |
497 | /// </summary> | 562 | /// </summary> |
@@ -623,7 +688,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
623 | 688 | ||
624 | Entities[presence.UUID] = presence; | 689 | Entities[presence.UUID] = presence; |
625 | 690 | ||
626 | lock (m_presenceLock) | 691 | m_scenePresencesLock.EnterWriteLock(); |
692 | try | ||
627 | { | 693 | { |
628 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 694 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
629 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 695 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -647,6 +713,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
647 | m_scenePresenceMap = newmap; | 713 | m_scenePresenceMap = newmap; |
648 | m_scenePresenceArray = newlist; | 714 | m_scenePresenceArray = newlist; |
649 | } | 715 | } |
716 | finally | ||
717 | { | ||
718 | m_scenePresencesLock.ExitWriteLock(); | ||
719 | } | ||
650 | } | 720 | } |
651 | 721 | ||
652 | /// <summary> | 722 | /// <summary> |
@@ -661,7 +731,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
661 | agentID); | 731 | agentID); |
662 | } | 732 | } |
663 | 733 | ||
664 | lock (m_presenceLock) | 734 | m_scenePresencesLock.EnterWriteLock(); |
735 | try | ||
665 | { | 736 | { |
666 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 737 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
667 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 738 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -683,6 +754,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
683 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 754 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
684 | } | 755 | } |
685 | } | 756 | } |
757 | finally | ||
758 | { | ||
759 | m_scenePresencesLock.ExitWriteLock(); | ||
760 | } | ||
686 | } | 761 | } |
687 | 762 | ||
688 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 763 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1396,8 +1471,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1396 | { | 1471 | { |
1397 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1472 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1398 | { | 1473 | { |
1399 | if (m_parentScene.AttachmentsModule != null) | 1474 | // Set the new attachment point data in the object |
1400 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1475 | byte attachmentPoint = group.GetAttachmentPoint(); |
1476 | group.UpdateGroupPosition(pos); | ||
1477 | group.IsAttachment = false; | ||
1478 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1479 | group.AttachmentPoint = attachmentPoint; | ||
1480 | group.HasGroupChanged = true; | ||
1401 | } | 1481 | } |
1402 | else | 1482 | else |
1403 | { | 1483 | { |
@@ -1661,24 +1741,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
1661 | /// <param name="childPrims"></param> | 1741 | /// <param name="childPrims"></param> |
1662 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1742 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1663 | { | 1743 | { |
1744 | SceneObjectGroup parentGroup = root.ParentGroup; | ||
1745 | if (parentGroup == null) return; | ||
1664 | Monitor.Enter(m_updateLock); | 1746 | Monitor.Enter(m_updateLock); |
1747 | |||
1665 | try | 1748 | try |
1666 | { | 1749 | { |
1667 | SceneObjectGroup parentGroup = root.ParentGroup; | 1750 | parentGroup.areUpdatesSuspended = true; |
1668 | 1751 | ||
1669 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1752 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1670 | 1753 | ||
1671 | // We do this in reverse to get the link order of the prims correct | 1754 | // We do this in reverse to get the link order of the prims correct |
1672 | for (int i = children.Count - 1; i >= 0; i--) | 1755 | for (int i = 0 ; i < children.Count ; i++) |
1673 | { | 1756 | { |
1674 | SceneObjectGroup child = children[i].ParentGroup; | 1757 | SceneObjectGroup child = children[i].ParentGroup; |
1675 | 1758 | ||
1676 | // Make sure no child prim is set for sale | 1759 | // Make sure no child prim is set for sale |
1677 | // So that, on delink, no prims are unwittingly | 1760 | // So that, on delink, no prims are unwittingly |
1678 | // left for sale and sold off | 1761 | // left for sale and sold off |
1679 | child.RootPart.ObjectSaleType = 0; | 1762 | |
1680 | child.RootPart.SalePrice = 10; | 1763 | if (child != null) |
1681 | childGroups.Add(child); | 1764 | { |
1765 | child.RootPart.ObjectSaleType = 0; | ||
1766 | child.RootPart.SalePrice = 10; | ||
1767 | childGroups.Add(child); | ||
1768 | } | ||
1682 | } | 1769 | } |
1683 | 1770 | ||
1684 | foreach (SceneObjectGroup child in childGroups) | 1771 | foreach (SceneObjectGroup child in childGroups) |
@@ -1694,12 +1781,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1694 | // occur on link to invoke this elsewhere (such as object selection) | 1781 | // occur on link to invoke this elsewhere (such as object selection) |
1695 | parentGroup.RootPart.CreateSelected = true; | 1782 | parentGroup.RootPart.CreateSelected = true; |
1696 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1783 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1697 | parentGroup.HasGroupChanged = true; | ||
1698 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1699 | |||
1700 | } | 1784 | } |
1701 | finally | 1785 | finally |
1702 | { | 1786 | { |
1787 | lock (SceneObjectGroupsByLocalPartID) | ||
1788 | { | ||
1789 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1790 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1791 | } | ||
1792 | |||
1793 | parentGroup.areUpdatesSuspended = false; | ||
1794 | parentGroup.HasGroupChanged = true; | ||
1795 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1796 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1703 | Monitor.Exit(m_updateLock); | 1797 | Monitor.Exit(m_updateLock); |
1704 | } | 1798 | } |
1705 | } | 1799 | } |
@@ -1731,21 +1825,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1731 | 1825 | ||
1732 | SceneObjectGroup group = part.ParentGroup; | 1826 | SceneObjectGroup group = part.ParentGroup; |
1733 | if (!affectedGroups.Contains(group)) | 1827 | if (!affectedGroups.Contains(group)) |
1828 | { | ||
1829 | group.areUpdatesSuspended = true; | ||
1734 | affectedGroups.Add(group); | 1830 | affectedGroups.Add(group); |
1831 | } | ||
1735 | } | 1832 | } |
1736 | } | 1833 | } |
1737 | } | 1834 | } |
1738 | 1835 | ||
1739 | foreach (SceneObjectPart child in childParts) | 1836 | if (childParts.Count > 0) |
1740 | { | 1837 | { |
1741 | // Unlink all child parts from their groups | 1838 | foreach (SceneObjectPart child in childParts) |
1742 | // | 1839 | { |
1743 | child.ParentGroup.DelinkFromGroup(child, true); | 1840 | // Unlink all child parts from their groups |
1744 | 1841 | // | |
1745 | // These are not in affected groups and will not be | 1842 | child.ParentGroup.DelinkFromGroup(child, true); |
1746 | // handled further. Do the honors here. | 1843 | child.ParentGroup.HasGroupChanged = true; |
1747 | child.ParentGroup.HasGroupChanged = true; | 1844 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1748 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1845 | } |
1749 | } | 1846 | } |
1750 | 1847 | ||
1751 | foreach (SceneObjectPart root in rootParts) | 1848 | foreach (SceneObjectPart root in rootParts) |
@@ -1755,56 +1852,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1755 | // However, editing linked parts and unlinking may be different | 1852 | // However, editing linked parts and unlinking may be different |
1756 | // | 1853 | // |
1757 | SceneObjectGroup group = root.ParentGroup; | 1854 | SceneObjectGroup group = root.ParentGroup; |
1855 | group.areUpdatesSuspended = true; | ||
1758 | 1856 | ||
1759 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1857 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1760 | int numChildren = newSet.Count; | 1858 | int numChildren = newSet.Count; |
1761 | 1859 | ||
1860 | if (numChildren == 1) | ||
1861 | break; | ||
1862 | |||
1762 | // If there are prims left in a link set, but the root is | 1863 | // If there are prims left in a link set, but the root is |
1763 | // slated for unlink, we need to do this | 1864 | // slated for unlink, we need to do this |
1865 | // Unlink the remaining set | ||
1764 | // | 1866 | // |
1765 | if (numChildren != 1) | 1867 | bool sendEventsToRemainder = true; |
1766 | { | 1868 | if (numChildren > 1) |
1767 | // Unlink the remaining set | 1869 | sendEventsToRemainder = false; |
1768 | // | ||
1769 | bool sendEventsToRemainder = true; | ||
1770 | if (numChildren > 1) | ||
1771 | sendEventsToRemainder = false; | ||
1772 | 1870 | ||
1773 | foreach (SceneObjectPart p in newSet) | 1871 | foreach (SceneObjectPart p in newSet) |
1872 | { | ||
1873 | if (p != group.RootPart) | ||
1774 | { | 1874 | { |
1775 | if (p != group.RootPart) | 1875 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1776 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1876 | if (numChildren > 2) |
1877 | { | ||
1878 | p.ParentGroup.areUpdatesSuspended = true; | ||
1879 | } | ||
1880 | else | ||
1881 | { | ||
1882 | p.ParentGroup.HasGroupChanged = true; | ||
1883 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1884 | } | ||
1777 | } | 1885 | } |
1886 | } | ||
1887 | |||
1888 | // If there is more than one prim remaining, we | ||
1889 | // need to re-link | ||
1890 | // | ||
1891 | if (numChildren > 2) | ||
1892 | { | ||
1893 | // Remove old root | ||
1894 | // | ||
1895 | if (newSet.Contains(root)) | ||
1896 | newSet.Remove(root); | ||
1778 | 1897 | ||
1779 | // If there is more than one prim remaining, we | 1898 | // Preserve link ordering |
1780 | // need to re-link | ||
1781 | // | 1899 | // |
1782 | if (numChildren > 2) | 1900 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1783 | { | 1901 | { |
1784 | // Remove old root | 1902 | return a.LinkNum.CompareTo(b.LinkNum); |
1785 | // | 1903 | }); |
1786 | if (newSet.Contains(root)) | ||
1787 | newSet.Remove(root); | ||
1788 | |||
1789 | // Preserve link ordering | ||
1790 | // | ||
1791 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1792 | { | ||
1793 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1794 | }); | ||
1795 | 1904 | ||
1796 | // Determine new root | 1905 | // Determine new root |
1797 | // | 1906 | // |
1798 | SceneObjectPart newRoot = newSet[0]; | 1907 | SceneObjectPart newRoot = newSet[0]; |
1799 | newSet.RemoveAt(0); | 1908 | newSet.RemoveAt(0); |
1800 | 1909 | ||
1801 | foreach (SceneObjectPart newChild in newSet) | 1910 | foreach (SceneObjectPart newChild in newSet) |
1802 | newChild.ClearUpdateSchedule(); | 1911 | newChild.ClearUpdateSchedule(); |
1803 | 1912 | ||
1804 | LinkObjects(newRoot, newSet); | 1913 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1805 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1914 | LinkObjects(newRoot, newSet); |
1806 | affectedGroups.Add(newRoot.ParentGroup); | 1915 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1807 | } | 1916 | affectedGroups.Add(newRoot.ParentGroup); |
1808 | } | 1917 | } |
1809 | } | 1918 | } |
1810 | 1919 | ||
@@ -1812,8 +1921,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1812 | // | 1921 | // |
1813 | foreach (SceneObjectGroup g in affectedGroups) | 1922 | foreach (SceneObjectGroup g in affectedGroups) |
1814 | { | 1923 | { |
1924 | // Child prims that have been unlinked and deleted will | ||
1925 | // return unless the root is deleted. This will remove them | ||
1926 | // from the database. They will be rewritten immediately, | ||
1927 | // minus the rows for the unlinked child prims. | ||
1928 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1815 | g.TriggerScriptChangedEvent(Changed.LINK); | 1929 | g.TriggerScriptChangedEvent(Changed.LINK); |
1816 | g.HasGroupChanged = true; // Persist | 1930 | g.HasGroupChanged = true; // Persist |
1931 | g.areUpdatesSuspended = false; | ||
1817 | g.ScheduleGroupForFullUpdate(); | 1932 | g.ScheduleGroupForFullUpdate(); |
1818 | } | 1933 | } |
1819 | } | 1934 | } |
@@ -1931,9 +2046,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1931 | child.ApplyNextOwnerPermissions(); | 2046 | child.ApplyNextOwnerPermissions(); |
1932 | } | 2047 | } |
1933 | } | 2048 | } |
1934 | |||
1935 | copy.RootPart.ObjectSaleType = 0; | ||
1936 | copy.RootPart.SalePrice = 10; | ||
1937 | } | 2049 | } |
1938 | 2050 | ||
1939 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2051 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |