clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Net;
30 using System.Collections.Generic;
31 using Nini.Config;
32 using OpenMetaverse;
33 using OpenSim.Data.Null;
34 using OpenSim.Framework;
35 using OpenSim.Framework.Communications;
36 using OpenSim.Framework.Console;
37 using OpenSim.Framework.Servers;
38 using OpenSim.Framework.Servers.HttpServer;
39 using OpenSim.Region.Physics.Manager;
40 using OpenSim.Region.Framework;
41 using OpenSim.Region.Framework.Interfaces;
42 using OpenSim.Region.Framework.Scenes;
43 using OpenSim.Region.CoreModules.Avatar.Gods;
44 using OpenSim.Region.CoreModules.Asset;
45 using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
46 using OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication;
47 using OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory;
48 using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid;
49 using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
50 using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence;
51 using OpenSim.Services.Interfaces;
52 using OpenSim.Tests.Common.Mock;
53 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
54  
55 namespace OpenSim.Tests.Common
56 {
57 /// <summary>
58 /// Helpers for setting up scenes.
59 /// </summary>
60 public class SceneHelpers
61 {
62 /// <summary>
63 /// We need a scene manager so that test clients can retrieve a scene when performing teleport tests.
64 /// </summary>
65 public SceneManager SceneManager { get; private set; }
66  
67 public ISimulationDataService SimDataService { get; private set; }
68  
69 private AgentCircuitManager m_acm = new AgentCircuitManager();
70 private IEstateDataService m_estateDataService = null;
71  
72 private LocalAssetServicesConnector m_assetService;
73 private LocalAuthenticationServicesConnector m_authenticationService;
74 private LocalInventoryServicesConnector m_inventoryService;
75 private LocalGridServicesConnector m_gridService;
76 private LocalUserAccountServicesConnector m_userAccountService;
77 private LocalPresenceServicesConnector m_presenceService;
78  
79 private CoreAssetCache m_cache;
80  
81 public SceneHelpers() : this(null) {}
82  
83 public SceneHelpers(CoreAssetCache cache)
84 {
85 SceneManager = new SceneManager();
86  
87 m_assetService = StartAssetService(cache);
88 m_authenticationService = StartAuthenticationService();
89 m_inventoryService = StartInventoryService();
90 m_gridService = StartGridService();
91 m_userAccountService = StartUserAccountService();
92 m_presenceService = StartPresenceService();
93  
94 m_inventoryService.PostInitialise();
95 m_assetService.PostInitialise();
96 m_userAccountService.PostInitialise();
97 m_presenceService.PostInitialise();
98  
99 m_cache = cache;
100  
101 SimDataService
102 = OpenSim.Server.Base.ServerUtils.LoadPlugin<ISimulationDataService>("OpenSim.Tests.Common.dll", null);
103 }
104  
105 /// <summary>
106 /// Set up a test scene
107 /// </summary>
108 /// <remarks>
109 /// Automatically starts services, as would the normal runtime.
110 /// </remarks>
111 /// <returns></returns>
112 public TestScene SetupScene()
113 {
114 return SetupScene("Unit test region", UUID.Random(), 1000, 1000);
115 }
116  
117 public TestScene SetupScene(string name, UUID id, uint x, uint y)
118 {
119 return SetupScene(name, id, x, y, new IniConfigSource());
120 }
121  
122 public TestScene SetupScene(string name, UUID id, uint x, uint y, IConfigSource configSource)
123 {
124 return SetupScene(name, id, x, y, Constants.RegionSize, Constants.RegionSize, configSource);
125 }
126  
127 /// <summary>
128 /// Set up a scene.
129 /// </summary>
130 /// <param name="name">Name of the region</param>
131 /// <param name="id">ID of the region</param>
132 /// <param name="x">X co-ordinate of the region</param>
133 /// <param name="y">Y co-ordinate of the region</param>
134 /// <param name="sizeX">X size of scene</param>
135 /// <param name="sizeY">Y size of scene</param>
136 /// <param name="configSource"></param>
137 /// <returns></returns>
138 public TestScene SetupScene(
139 string name, UUID id, uint x, uint y, uint sizeX, uint sizeY, IConfigSource configSource)
140 {
141 Console.WriteLine("Setting up test scene {0}", name);
142  
143 // We must set up a console otherwise setup of some modules may fail
144 MainConsole.Instance = new MockConsole();
145  
146 RegionInfo regInfo = new RegionInfo(x, y, new IPEndPoint(IPAddress.Loopback, 9000), "127.0.0.1");
147 regInfo.RegionName = name;
148 regInfo.RegionID = id;
149 regInfo.RegionSizeX = sizeX;
150 regInfo.RegionSizeY = sizeY;
151  
152 SceneCommunicationService scs = new SceneCommunicationService();
153  
154 PhysicsPluginManager physicsPluginManager = new PhysicsPluginManager();
155 physicsPluginManager.LoadPluginsFromAssembly("Physics/OpenSim.Region.Physics.BasicPhysicsPlugin.dll");
156 Vector3 regionExtent = new Vector3( regInfo.RegionSizeX, regInfo.RegionSizeY, regInfo.RegionSizeZ);
157 PhysicsScene physicsScene
158 = physicsPluginManager.GetPhysicsScene(
159 "basicphysics", "ZeroMesher", new IniConfigSource(), "test", regionExtent);
160  
161 TestScene testScene = new TestScene(
162 regInfo, m_acm, physicsScene, scs, SimDataService, m_estateDataService, configSource, null);
163  
164 INonSharedRegionModule godsModule = new GodsModule();
165 godsModule.Initialise(new IniConfigSource());
166 godsModule.AddRegion(testScene);
167  
168 // Add scene to services
169 m_assetService.AddRegion(testScene);
170  
171 if (m_cache != null)
172 {
173 m_cache.AddRegion(testScene);
174 m_cache.RegionLoaded(testScene);
175 testScene.AddRegionModule(m_cache.Name, m_cache);
176 }
177  
178 m_assetService.RegionLoaded(testScene);
179 testScene.AddRegionModule(m_assetService.Name, m_assetService);
180  
181 m_authenticationService.AddRegion(testScene);
182 m_authenticationService.RegionLoaded(testScene);
183 testScene.AddRegionModule(m_authenticationService.Name, m_authenticationService);
184  
185 m_inventoryService.AddRegion(testScene);
186 m_inventoryService.RegionLoaded(testScene);
187 testScene.AddRegionModule(m_inventoryService.Name, m_inventoryService);
188  
189 m_gridService.AddRegion(testScene);
190 m_gridService.RegionLoaded(testScene);
191 testScene.AddRegionModule(m_gridService.Name, m_gridService);
192  
193 m_userAccountService.AddRegion(testScene);
194 m_userAccountService.RegionLoaded(testScene);
195 testScene.AddRegionModule(m_userAccountService.Name, m_userAccountService);
196  
197 m_presenceService.AddRegion(testScene);
198 m_presenceService.RegionLoaded(testScene);
199 testScene.AddRegionModule(m_presenceService.Name, m_presenceService);
200  
201 testScene.RegionInfo.EstateSettings.EstateOwner = UUID.Random();
202 testScene.SetModuleInterfaces();
203  
204 testScene.LandChannel = new TestLandChannel(testScene);
205 testScene.LoadWorldMap();
206  
207 testScene.RegionInfo.EstateSettings = new EstateSettings();
208 testScene.LoginsEnabled = true;
209 testScene.RegisterRegionWithGrid();
210  
211 SceneManager.Add(testScene);
212  
213 return testScene;
214 }
215  
216 private static LocalAssetServicesConnector StartAssetService(CoreAssetCache cache)
217 {
218 IConfigSource config = new IniConfigSource();
219 config.AddConfig("Modules");
220 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
221 config.AddConfig("AssetService");
222 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
223 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
224  
225 LocalAssetServicesConnector assetService = new LocalAssetServicesConnector();
226 assetService.Initialise(config);
227  
228 if (cache != null)
229 {
230 IConfigSource cacheConfig = new IniConfigSource();
231 cacheConfig.AddConfig("Modules");
232 cacheConfig.Configs["Modules"].Set("AssetCaching", "CoreAssetCache");
233 cacheConfig.AddConfig("AssetCache");
234  
235 cache.Initialise(cacheConfig);
236 }
237  
238 return assetService;
239 }
240  
241 private static LocalAuthenticationServicesConnector StartAuthenticationService()
242 {
243 IConfigSource config = new IniConfigSource();
244 config.AddConfig("Modules");
245 config.AddConfig("AuthenticationService");
246 config.Configs["Modules"].Set("AuthenticationServices", "LocalAuthenticationServicesConnector");
247 config.Configs["AuthenticationService"].Set(
248 "LocalServiceModule", "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService");
249 config.Configs["AuthenticationService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
250  
251 LocalAuthenticationServicesConnector service = new LocalAuthenticationServicesConnector();
252 service.Initialise(config);
253  
254 return service;
255 }
256  
257 private static LocalInventoryServicesConnector StartInventoryService()
258 {
259 IConfigSource config = new IniConfigSource();
260 config.AddConfig("Modules");
261 config.AddConfig("InventoryService");
262 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
263 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
264 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
265  
266 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
267 inventoryService.Initialise(config);
268  
269 return inventoryService;
270 }
271  
272 private static LocalGridServicesConnector StartGridService()
273 {
274 IConfigSource config = new IniConfigSource();
275 config.AddConfig("Modules");
276 config.AddConfig("GridService");
277 config.Configs["Modules"].Set("GridServices", "LocalGridServicesConnector");
278 config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData");
279 config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService");
280 config.Configs["GridService"].Set("ConnectionString", "!static");
281  
282 LocalGridServicesConnector gridService = new LocalGridServicesConnector();
283 gridService.Initialise(config);
284  
285 return gridService;
286 }
287  
288 /// <summary>
289 /// Start a user account service
290 /// </summary>
291 /// <param name="testScene"></param>
292 /// <returns></returns>
293 private static LocalUserAccountServicesConnector StartUserAccountService()
294 {
295 IConfigSource config = new IniConfigSource();
296 config.AddConfig("Modules");
297 config.AddConfig("UserAccountService");
298 config.Configs["Modules"].Set("UserAccountServices", "LocalUserAccountServicesConnector");
299 config.Configs["UserAccountService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
300 config.Configs["UserAccountService"].Set(
301 "LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService");
302  
303 LocalUserAccountServicesConnector userAccountService = new LocalUserAccountServicesConnector();
304 userAccountService.Initialise(config);
305  
306 return userAccountService;
307 }
308  
309 /// <summary>
310 /// Start a presence service
311 /// </summary>
312 /// <param name="testScene"></param>
313 private static LocalPresenceServicesConnector StartPresenceService()
314 {
315 // Unfortunately, some services share data via statics, so we need to null every time to stop interference
316 // between tests.
317 // This is a massive non-obvious pita.
318 NullPresenceData.Instance = null;
319  
320 IConfigSource config = new IniConfigSource();
321 config.AddConfig("Modules");
322 config.AddConfig("PresenceService");
323 config.Configs["Modules"].Set("PresenceServices", "LocalPresenceServicesConnector");
324 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
325 config.Configs["PresenceService"].Set(
326 "LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService");
327  
328 LocalPresenceServicesConnector presenceService = new LocalPresenceServicesConnector();
329 presenceService.Initialise(config);
330  
331 return presenceService;
332 }
333  
334 /// <summary>
335 /// Setup modules for a scene using their default settings.
336 /// </summary>
337 /// <param name="scene"></param>
338 /// <param name="modules"></param>
339 public static void SetupSceneModules(Scene scene, params object[] modules)
340 {
341 SetupSceneModules(scene, new IniConfigSource(), modules);
342 }
343  
344 /// <summary>
345 /// Setup modules for a scene.
346 /// </summary>
347 /// <remarks>
348 /// If called directly, then all the modules must be shared modules.
349 /// </remarks>
350 /// <param name="scenes"></param>
351 /// <param name="config"></param>
352 /// <param name="modules"></param>
353 public static void SetupSceneModules(Scene scene, IConfigSource config, params object[] modules)
354 {
355 SetupSceneModules(new Scene[] { scene }, config, modules);
356 }
357  
358 /// <summary>
359 /// Setup modules for a scene using their default settings.
360 /// </summary>
361 /// <param name="scenes"></param>
362 /// <param name="modules"></param>
363 public static void SetupSceneModules(Scene[] scenes, params object[] modules)
364 {
365 SetupSceneModules(scenes, new IniConfigSource(), modules);
366 }
367  
368 /// <summary>
369 /// Setup modules for scenes.
370 /// </summary>
371 /// <remarks>
372 /// If called directly, then all the modules must be shared modules.
373 ///
374 /// We are emulating here the normal calls made to setup region modules
375 /// (Initialise(), PostInitialise(), AddRegion, RegionLoaded()).
376 /// TODO: Need to reuse normal runtime module code.
377 /// </remarks>
378 /// <param name="scenes"></param>
379 /// <param name="config"></param>
380 /// <param name="modules"></param>
381 public static void SetupSceneModules(Scene[] scenes, IConfigSource config, params object[] modules)
382 {
383 List<IRegionModuleBase> newModules = new List<IRegionModuleBase>();
384 foreach (object module in modules)
385 {
386 IRegionModuleBase m = (IRegionModuleBase)module;
387 // Console.WriteLine("MODULE {0}", m.Name);
388 m.Initialise(config);
389 newModules.Add(m);
390 }
391  
392 foreach (IRegionModuleBase module in newModules)
393 {
394 if (module is ISharedRegionModule) ((ISharedRegionModule)module).PostInitialise();
395 }
396  
397 foreach (IRegionModuleBase module in newModules)
398 {
399 foreach (Scene scene in scenes)
400 {
401 module.AddRegion(scene);
402 scene.AddRegionModule(module.Name, module);
403 }
404 }
405  
406 // RegionLoaded is fired after all modules have been appropriately added to all scenes
407 foreach (IRegionModuleBase module in newModules)
408 foreach (Scene scene in scenes)
409 module.RegionLoaded(scene);
410  
411 foreach (Scene scene in scenes) { scene.SetModuleInterfaces(); }
412 }
413  
414 /// <summary>
415 /// Generate some standard agent connection data.
416 /// </summary>
417 /// <param name="agentId"></param>
418 /// <returns></returns>
419 public static AgentCircuitData GenerateAgentData(UUID agentId)
420 {
421 AgentCircuitData acd = GenerateCommonAgentData();
422  
423 acd.AgentID = agentId;
424 acd.firstname = "testfirstname";
425 acd.lastname = "testlastname";
426 acd.ServiceURLs = new Dictionary<string, object>();
427  
428 return acd;
429 }
430  
431 /// <summary>
432 /// Generate some standard agent connection data.
433 /// </summary>
434 /// <param name="agentId"></param>
435 /// <returns></returns>
436 public static AgentCircuitData GenerateAgentData(UserAccount ua)
437 {
438 AgentCircuitData acd = GenerateCommonAgentData();
439  
440 acd.AgentID = ua.PrincipalID;
441 acd.firstname = ua.FirstName;
442 acd.lastname = ua.LastName;
443 acd.ServiceURLs = ua.ServiceURLs;
444  
445 return acd;
446 }
447  
448 private static AgentCircuitData GenerateCommonAgentData()
449 {
450 AgentCircuitData acd = new AgentCircuitData();
451  
452 // XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData.
453 acd.SessionID = UUID.Random();
454 acd.SecureSessionID = UUID.Random();
455  
456 acd.circuitcode = 123;
457 acd.BaseFolder = UUID.Zero;
458 acd.InventoryFolder = UUID.Zero;
459 acd.startpos = Vector3.Zero;
460 acd.CapsPath = "http://wibble.com";
461 acd.Appearance = new AvatarAppearance();
462  
463 return acd;
464 }
465  
466 /// <summary>
467 /// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
468 /// </summary>
469 /// <remarks>
470 /// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will
471 /// make the agent circuit data (e.g. first, lastname) consistent with the user account data.
472 /// </remarks>
473 /// <param name="scene"></param>
474 /// <param name="agentId"></param>
475 /// <returns></returns>
476 public static ScenePresence AddScenePresence(Scene scene, UUID agentId)
477 {
478 return AddScenePresence(scene, GenerateAgentData(agentId));
479 }
480  
481 /// <summary>
482 /// Add a root agent.
483 /// </summary>
484 /// <param name="scene"></param>
485 /// <param name="ua"></param>
486 /// <returns></returns>
487 public static ScenePresence AddScenePresence(Scene scene, UserAccount ua)
488 {
489 return AddScenePresence(scene, GenerateAgentData(ua));
490 }
491  
492 /// <summary>
493 /// Add a root agent.
494 /// </summary>
495 /// <remarks>
496 /// This function
497 ///
498 /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the
499 /// userserver if grid) would give initial login data back to the client and separately tell the scene that the
500 /// agent was coming.
501 ///
502 /// 2) Connects the agent with the scene
503 ///
504 /// This function performs actions equivalent with notifying the scene that an agent is
505 /// coming and then actually connecting the agent to the scene. The one step missed out is the very first
506 /// </remarks>
507 /// <param name="scene"></param>
508 /// <param name="agentData"></param>
509 /// <returns></returns>
510 public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData)
511 {
512 return AddScenePresence(scene, new TestClient(agentData, scene), agentData);
513 }
514  
515 /// <summary>
516 /// Add a root agent.
517 /// </summary>
518 /// <remarks>
519 /// This function
520 ///
521 /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the
522 /// userserver if grid) would give initial login data back to the client and separately tell the scene that the
523 /// agent was coming.
524 ///
525 /// 2) Connects the agent with the scene
526 ///
527 /// This function performs actions equivalent with notifying the scene that an agent is
528 /// coming and then actually connecting the agent to the scene. The one step missed out is the very first
529 /// </remarks>
530 /// <param name="scene"></param>
531 /// <param name="agentData"></param>
532 /// <returns></returns>
533 public static ScenePresence AddScenePresence(
534 Scene scene, IClientAPI client, AgentCircuitData agentData)
535 {
536 // We emulate the proper login sequence here by doing things in four stages
537  
538 // Stage 0: login
539 // We need to punch through to the underlying service because scene will not, correctly, let us call it
540 // through it's reference to the LPSC
541 LocalPresenceServicesConnector lpsc = (LocalPresenceServicesConnector)scene.PresenceService;
542 lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID);
543  
544 // Stages 1 & 2
545 ScenePresence sp = IntroduceClientToScene(scene, client, agentData, TeleportFlags.ViaLogin);
546  
547 // Stage 3: Complete the entrance into the region. This converts the child agent into a root agent.
548 sp.CompleteMovement(sp.ControllingClient, true);
549  
550 return sp;
551 }
552  
553 /// <summary>
554 /// Introduce an agent into the scene by adding a new client.
555 /// </summary>
556 /// <returns>The scene presence added</returns>
557 /// <param name='scene'></param>
558 /// <param name='testClient'></param>
559 /// <param name='agentData'></param>
560 /// <param name='tf'></param>
561 private static ScenePresence IntroduceClientToScene(
562 Scene scene, IClientAPI client, AgentCircuitData agentData, TeleportFlags tf)
563 {
564 string reason;
565  
566 // Stage 1: tell the scene to expect a new user connection
567 if (!scene.NewUserConnection(agentData, (uint)tf, null, out reason))
568 Console.WriteLine("NewUserConnection failed: " + reason);
569  
570 // Stage 2: add the new client as a child agent to the scene
571 scene.AddNewAgent(client, PresenceType.User);
572  
573 return scene.GetScenePresence(client.AgentId);
574 }
575  
576 public static ScenePresence AddChildScenePresence(Scene scene, UUID agentId)
577 {
578 return AddChildScenePresence(scene, GenerateAgentData(agentId));
579 }
580  
581 public static ScenePresence AddChildScenePresence(Scene scene, AgentCircuitData acd)
582 {
583 acd.child = true;
584  
585 // XXX: ViaLogin may not be correct for child agents
586 TestClient client = new TestClient(acd, scene);
587 return IntroduceClientToScene(scene, client, acd, TeleportFlags.ViaLogin);
588 }
589  
590 /// <summary>
591 /// Add a test object
592 /// </summary>
593 /// <param name="scene"></param>
594 /// <returns></returns>
595 public static SceneObjectGroup AddSceneObject(Scene scene)
596 {
597 return AddSceneObject(scene, "Test Object", UUID.Zero);
598 }
599  
600 /// <summary>
601 /// Add a test object
602 /// </summary>
603 /// <param name="scene"></param>
604 /// <param name="name"></param>
605 /// <param name="ownerId"></param>
606 /// <returns></returns>
607 public static SceneObjectGroup AddSceneObject(Scene scene, string name, UUID ownerId)
608 {
609 SceneObjectGroup so = new SceneObjectGroup(CreateSceneObjectPart(name, UUID.Random(), ownerId));
610  
611 //part.UpdatePrimFlags(false, false, true);
612 //part.ObjectFlags |= (uint)PrimFlags.Phantom;
613  
614 scene.AddNewSceneObject(so, false);
615  
616 return so;
617 }
618  
619 /// <summary>
620 /// Add a test object
621 /// </summary>
622 /// <param name="scene"></param>
623 /// <param name="parts">
624 /// The number of parts that should be in the scene object
625 /// </param>
626 /// <param name="ownerId"></param>
627 /// <param name="partNamePrefix">
628 /// The prefix to be given to part names. This will be suffixed with "Part<part no>"
629 /// (e.g. mynamePart1 for the root part)
630 /// </param>
631 /// <param name="uuidTail">
632 /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}"
633 /// will be given to the root part, and incremented for each part thereafter.
634 /// </param>
635 /// <returns></returns>
636 public static SceneObjectGroup AddSceneObject(Scene scene, int parts, UUID ownerId, string partNamePrefix, int uuidTail)
637 {
638 SceneObjectGroup so = CreateSceneObject(parts, ownerId, partNamePrefix, uuidTail);
639  
640 scene.AddNewSceneObject(so, false);
641  
642 return so;
643 }
644  
645 /// <summary>
646 /// Create a scene object part.
647 /// </summary>
648 /// <param name="name"></param>
649 /// <param name="id"></param>
650 /// <param name="ownerId"></param>
651 /// <returns></returns>
652 public static SceneObjectPart CreateSceneObjectPart(string name, UUID id, UUID ownerId)
653 {
654 return new SceneObjectPart(
655 ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
656 { Name = name, UUID = id, Scale = new Vector3(1, 1, 1) };
657 }
658  
659 /// <summary>
660 /// Create a scene object but do not add it to the scene.
661 /// </summary>
662 /// <remarks>
663 /// UUID always starts at 00000000-0000-0000-0000-000000000001. For some purposes, (e.g. serializing direct
664 /// to another object's inventory) we do not need a scene unique ID. So it would be better to add the
665 /// UUID when we actually add an object to a scene rather than on creation.
666 /// </remarks>
667 /// <param name="parts">The number of parts that should be in the scene object</param>
668 /// <param name="ownerId"></param>
669 /// <returns></returns>
670 public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId)
671 {
672 return CreateSceneObject(parts, ownerId, 0x1);
673 }
674  
675 /// <summary>
676 /// Create a scene object but do not add it to the scene.
677 /// </summary>
678 /// <param name="parts">The number of parts that should be in the scene object</param>
679 /// <param name="ownerId"></param>
680 /// <param name="uuidTail">
681 /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}"
682 /// will be given to the root part, and incremented for each part thereafter.
683 /// </param>
684 /// <returns></returns>
685 public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail)
686 {
687 return CreateSceneObject(parts, ownerId, "", uuidTail);
688 }
689  
690 /// <summary>
691 /// Create a scene object but do not add it to the scene.
692 /// </summary>
693 /// <param name="parts">
694 /// The number of parts that should be in the scene object
695 /// </param>
696 /// <param name="ownerId"></param>
697 /// <param name="partNamePrefix">
698 /// The prefix to be given to part names. This will be suffixed with "Part<part no>"
699 /// (e.g. mynamePart1 for the root part)
700 /// </param>
701 /// <param name="uuidTail">
702 /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}"
703 /// will be given to the root part, and incremented for each part thereafter.
704 /// </param>
705 /// <returns></returns>
706 public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, string partNamePrefix, int uuidTail)
707 {
708 string rawSogId = string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail);
709  
710 SceneObjectGroup sog
711 = new SceneObjectGroup(
712 CreateSceneObjectPart(string.Format("{0}Part1", partNamePrefix), new UUID(rawSogId), ownerId));
713  
714 if (parts > 1)
715 for (int i = 2; i <= parts; i++)
716 sog.AddPart(
717 CreateSceneObjectPart(
718 string.Format("{0}Part{1}", partNamePrefix, i),
719 new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail + i - 1)),
720 ownerId));
721  
722 return sog;
723 }
724 }
725 }