public ulong GetPhysicsKey() { ulong hash = 5381; // Nice prime to start with Primitive.ConstructionData data = Prim.PrimData; hash = Util.djb2(hash, (byte)data.PathCurve); hash = Util.djb2(hash, (byte)((byte)data.ProfileHole | (byte)data.ProfileCurve)); hash = Util.djb2(hash, data.PathBegin); hash = Util.djb2(hash, data.PathEnd); hash = Util.djb2(hash, data.PathScaleX); hash = Util.djb2(hash, data.PathScaleY); hash = Util.djb2(hash, data.PathShearX); hash = Util.djb2(hash, data.PathShearY); hash = Util.djb2(hash, data.PathTwist); hash = Util.djb2(hash, data.PathTwistBegin); hash = Util.djb2(hash, data.PathRadiusOffset); hash = Util.djb2(hash, data.PathTaperX); hash = Util.djb2(hash, data.PathTaperY); hash = Util.djb2(hash, data.PathRevolutions); hash = Util.djb2(hash, data.PathSkew); hash = Util.djb2(hash, data.ProfileBegin); hash = Util.djb2(hash, data.ProfileEnd); hash = Util.djb2(hash, data.ProfileHollow); // Include sculpt data if it exists if (Prim.Sculpt != null && Prim.Sculpt.SculptTexture != UUID.Zero) { byte[] sculptBytes = Prim.Sculpt.GetBytes(); for (int i = 0; i < sculptBytes.Length; i++) hash = Util.djb2(hash, sculptBytes[i]); } return hash; }
private static Primitive.ConstructionData FromPrimObjectShape(PrimObject.ShapeBlock objShape, int pcode, int material) { Primitive.ConstructionData shape = new Primitive.ConstructionData(); shape.PCode = (PCode)pcode; shape.Material = (Material)material; shape.PathBegin = objShape.PathBegin; shape.PathCurve = (PathCurve)objShape.PathCurve; shape.PathEnd = objShape.PathEnd; shape.PathRadiusOffset = objShape.PathRadiusOffset; shape.PathRevolutions = objShape.PathRevolutions; shape.PathScaleX = objShape.PathScaleX; shape.PathScaleY = objShape.PathScaleY; shape.PathShearX = objShape.PathShearX; shape.PathShearY = objShape.PathShearY; shape.PathSkew = objShape.PathSkew; shape.PathTaperX = objShape.PathTaperX; shape.PathTaperY = objShape.PathTaperY; shape.PathTwist = objShape.PathTwist; shape.PathTwistBegin = objShape.PathTwistBegin; shape.ProfileBegin = objShape.ProfileBegin; shape.ProfileCurve = (ProfileCurve)objShape.ProfileCurve; shape.ProfileEnd = objShape.ProfileEnd; shape.ProfileHollow = objShape.ProfileHollow; return(shape); }
public PhysicsType GetPhysicsType() { const float MIN_MESH_SIZE_SQ = 0.2f * 0.2f; Primitive.ConstructionData shape = Prim.PrimData; // Anything smaller than MIN_MESH_SIZE will become a simple cube if (Prim.Scale.LengthSquared() < MIN_MESH_SIZE_SQ) { return PhysicsType.Box; } else if (shape.ProfileCurve == ProfileCurve.Square && shape.PathCurve == PathCurve.Line) { if (HasBasicShape(shape)) return PhysicsType.Box; } else if (shape.ProfileCurve == ProfileCurve.HalfCircle && shape.PathCurve == PathCurve.Circle) { if (HasBasicShape(shape)) return PhysicsType.Sphere; } // TODO: Figure out what the problem with cylinders is //else if (shape.ProfileCurve == ProfileCurve.Circle && shape.PathCurve == PathCurve.Line) //{ // if (HasBasicShape(shape)) // return PhysicsType.Cylinder; //} return PhysicsType.ConvexHull; }
private static bool HasBasicShape(Primitive.ConstructionData shape) { return shape.ProfileBegin == 0f && shape.ProfileEnd == 1f && shape.ProfileHollow == 0f && shape.PathTwistBegin == 0f && shape.PathTwist == 0f && shape.PathBegin == 0f && shape.PathEnd == 1f && shape.PathTaperX == 0f && shape.PathTaperY == 0f && shape.PathScaleX == 1f && shape.PathScaleY == 1f && shape.PathShearX == 0f && shape.PathShearY == 0f; }
public void ObjectModify(object sender, SimulationObject obj, Primitive.ConstructionData data) { if (OnObjectModify != null) { OnObjectModify(sender, obj, data); } // Update the object obj.Prim.PrimData = data; // Inform clients BroadcastObjectUpdate(obj); }
void ObjectShapeHandler(Packet packet, Agent agent) { ObjectShapePacket shape = (ObjectShapePacket)packet; for (int i = 0; i < shape.ObjectData.Length; i++) { ObjectShapePacket.ObjectDataBlock block = shape.ObjectData[i]; SimulationObject obj; if (server.Scene.TryGetObject(block.ObjectLocalID, out obj)) { Primitive.ConstructionData data = obj.Prim.PrimData; data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin); data.PathCurve = (PathCurve)block.PathCurve; data.PathEnd = Primitive.UnpackEndCut(block.PathEnd); data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset); data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions); data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX); data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY); data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX); data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY); data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew); data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX); data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY); data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist); data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin); data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin); data.profileCurve = block.ProfileCurve; data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd); data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); server.Scene.ObjectModify(this, obj, data); } else { Logger.Log("Got an ObjectShape packet for unknown object " + block.ObjectLocalID, Helpers.LogLevel.Warning); } } }
private void BuildAndRez(PrimType primType) { float size, distance; size = (float)tbox_Size.Value; distance = (float)tbox_Distance.Value; Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(primType); Vector3 rezpos = new Vector3(distance, 0, 0); rezpos = client.Self.SimPosition + rezpos * client.Self.Movement.BodyRotation; ObjectName = txt_ObjectName.Text; client.Objects.ObjectUpdate += new EventHandler <PrimEventArgs>(Objects_OnNewPrim); client.Objects.AddPrim(client.Network.CurrentSim, primData, UUID.Zero, rezpos, new Vector3(size), Quaternion.Identity); if (!primDone.WaitOne(10000, false)) { throw new Exception("Rez failed, timed out while creating the prim."); } txt_ObjectName.Text = ObjectName; }
static void Main(string[] args) { if (args.Length != 8 && args.Length != 9) { Console.WriteLine("Usage: importprimscript.exe [firstname] [lastname] [password] " + "[loginuri] [Simulator] [x] [y] [z] [input.primscript]" + Environment.NewLine + "Example: importprimscript.exe My Bot password " + "Hooper 128 128 40 maya-export" + Path.DirectorySeparatorChar + "ant.primscript" + Environment.NewLine + "(the loginuri is optional and only used for logging in to another grid)"); Environment.Exit(-1); } // Strip quotes from any arguments for (int i = 0; i < args.Length; i++) { args[i] = args[i].Trim(new char[] { '"' }); } // Parse the primscript file string scriptfilename = args[args.Length - 1]; string error; List <Sculpt> sculpties = ParsePrimscript(scriptfilename, out error); scriptfilename = Path.GetFileNameWithoutExtension(scriptfilename); // Check for parsing errors if (error != String.Empty) { Console.WriteLine("An error was encountered reading the input file: " + error); Environment.Exit(-2); } else if (sculpties.Count == 0) { Console.WriteLine("No primitives were read from the input file"); Environment.Exit(-3); } // Add callback handlers for asset uploads finishing. new prims spotted, and logging Client.Objects.ObjectUpdate += new EventHandler <PrimEventArgs>(Objects_OnNewPrim); Logger.OnLogMessage += new Logger.LogCallback(Client_OnLogMessage); // Optimize the connection for our purposes Client.Self.Movement.Camera.Far = 64f; Client.Settings.MULTIPLE_SIMS = false; Client.Settings.SEND_AGENT_UPDATES = true; Settings.LOG_LEVEL = Helpers.LogLevel.None; Client.Settings.ALWAYS_REQUEST_OBJECTS = true; Client.Settings.ALWAYS_DECODE_OBJECTS = true; Client.Settings.THROTTLE_OUTGOING_PACKETS = false; Client.Throttle.Land = 0; Client.Throttle.Wind = 0; Client.Throttle.Cloud = 0; // Not sure if Asset or Texture will help with uploads, but it won't hurt Client.Throttle.Asset = 220000.0f; Client.Throttle.Texture = 446000.0f; Client.Throttle.Task = 446000.0f; // Create a handler for the event queue connecting, so we know when // it is safe to start uploading AutoResetEvent eventQueueEvent = new AutoResetEvent(false); EventHandler <EventQueueRunningEventArgs> eventQueueCallback = delegate(object sender, EventQueueRunningEventArgs e) { if (e.Simulator == Client.Network.CurrentSim) { eventQueueEvent.Set(); } }; Client.Network.EventQueueRunning += eventQueueCallback; int x = Int32.Parse(args[args.Length - 4]); int y = Int32.Parse(args[args.Length - 3]); int z = Int32.Parse(args[args.Length - 2]); string start = NetworkManager.StartLocation(args[args.Length - 5], x, y, z); LoginParams loginParams = Client.Network.DefaultLoginParams(args[0], args[1], args[2], "importprimscript", "1.4.0"); loginParams.Start = start; if (args.Length == 9) { loginParams.URI = args[3]; } // Attempt to login if (!Client.Network.Login(loginParams)) { Console.WriteLine("Login failed: " + Client.Network.LoginMessage); Environment.Exit(-4); } // Need to be connected to the event queue before we can upload Console.WriteLine("Login succeeded, waiting for the event handler to connect..."); if (!eventQueueEvent.WaitOne(1000 * 90, false)) { Console.WriteLine("Event queue connection timed out, disconnecting..."); Client.Network.Logout(); Environment.Exit(-5); } // Don't need this anymore Client.Network.EventQueueRunning -= eventQueueCallback; // Set the root position for the import RootPosition = Client.Self.SimPosition; RootPosition.Z += 3.0f; // TODO: Check if our account balance is high enough to upload everything // // Create a folder to hold all of our texture uploads UploadFolderID = Client.Inventory.CreateFolder(Client.Inventory.Store.RootFolder.UUID, scriptfilename); // Loop through each sculpty and do what we need to do for (int i = 0; i < sculpties.Count; i++) { // Upload the sculpt map and texture sculpties[i].SculptID = UploadImage(sculpties[i].SculptFile, true); sculpties[i].TextureID = UploadImage(sculpties[i].TextureFile, false); // Check for failed uploads if (sculpties[i].SculptID == UUID.Zero) { Console.WriteLine("Sculpt map " + sculpties[i].SculptFile + " failed to upload, skipping " + sculpties[i].Name); continue; } else if (sculpties[i].TextureID == UUID.Zero) { Console.WriteLine("Texture " + sculpties[i].TextureFile + " failed to upload, skipping " + sculpties[i].Name); continue; } // Create basic spherical volume parameters. It will be set to // a scultpy in the callback for new objects being created Primitive.ConstructionData volume = new Primitive.ConstructionData(); volume.PCode = PCode.Prim; volume.Material = Material.Wood; volume.PathScaleY = 0.5f; volume.PathCurve = PathCurve.Circle; volume.ProfileCurve = ProfileCurve.Circle; // Rez this prim CurrentSculpt = sculpties[i]; Client.Objects.AddPrim(Client.Network.CurrentSim, volume, UUID.Zero, RootPosition + CurrentSculpt.Offset, CurrentSculpt.Scale, Quaternion.Identity); // Wait for the prim to rez and the properties be set for it if (!RezzedEvent.WaitOne(1000 * 10, false)) { Console.WriteLine("Timed out waiting for prim " + CurrentSculpt.Name + " to rez, skipping"); continue; } } CurrentSculpt = null; lock (RezzedPrims) { // Set full permissions for all of the objects Client.Objects.SetPermissions(Client.Network.CurrentSim, RezzedPrims, PermissionWho.All, PermissionMask.All, true); // Link the entire object together Client.Objects.LinkPrims(Client.Network.CurrentSim, RezzedPrims); } Console.WriteLine("Rezzed, textured, and linked " + RezzedPrims.Count + " sculpted prims, logging out..."); Client.Network.Logout(); }
public ObjectDataBlockUpdateEventArgs(Simulator simulator, Primitive prim, Primitive.ConstructionData constructionData, ObjectUpdatePacket.ObjectDataBlock block, ObjectMovementUpdate objectupdate, NameValue[] nameValues) { this.m_Simulator = simulator; this.m_Prim = prim; this.m_ConstructionData = constructionData; this.m_Block = block; this.m_Update = objectupdate; this.m_NameValues = nameValues; }
/// <summary> /// Setup construction data for a basic primitive shape /// </summary> /// <param name="type">Primitive shape to construct</param> /// <returns>Construction data that can be plugged into a <seealso cref="Primitive"/></returns> public static Primitive.ConstructionData BuildBasicShape(PrimType type) { Primitive.ConstructionData prim = new Primitive.ConstructionData(); prim.PCode = PCode.Prim; prim.Material = Material.Wood; switch (type) { case PrimType.Box: prim.ProfileCurve = ProfileCurve.Square; prim.PathCurve = PathCurve.Line; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 1f; prim.PathRevolutions = 1f; break; case PrimType.Cylinder: prim.ProfileCurve = ProfileCurve.Circle; prim.PathCurve = PathCurve.Line; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 1f; prim.PathRevolutions = 1f; break; case PrimType.Prism: prim.ProfileCurve = ProfileCurve.Square; prim.PathCurve = PathCurve.Line; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 0f; prim.PathScaleY = 0f; prim.PathRevolutions = 1f; break; case PrimType.Ring: prim.ProfileCurve = ProfileCurve.EqualTriangle; prim.PathCurve = PathCurve.Circle; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 0.25f; prim.PathRevolutions = 1f; break; case PrimType.Sphere: prim.ProfileCurve = ProfileCurve.HalfCircle; prim.PathCurve = PathCurve.Circle; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 1f; prim.PathRevolutions = 1f; break; case PrimType.Torus: prim.ProfileCurve = ProfileCurve.Circle; prim.PathCurve = PathCurve.Circle; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 0.25f; prim.PathRevolutions = 1f; break; case PrimType.Tube: prim.ProfileCurve = ProfileCurve.Square; prim.PathCurve = PathCurve.Circle; prim.ProfileEnd = 1f; prim.PathEnd = 1f; prim.PathScaleX = 1f; prim.PathScaleY = 0.25f; prim.PathRevolutions = 1f; break; default: throw new NotSupportedException("Unsupported shape: " + type.ToString()); } return prim; }
/// <summary>Process an incoming packet and raise the appropriate events</summary> /// <param name="sender">The sender</param> /// <param name="e">The EventArgs object containing the packet data</param> protected void ObjectUpdateHandler(object sender, PacketReceivedEventArgs e) { Packet packet = e.Packet; Simulator simulator = e.Simulator; ObjectUpdatePacket update = (ObjectUpdatePacket)packet; UpdateDilation(e.Simulator, update.RegionData.TimeDilation); for (int b = 0; b < update.ObjectData.Length; b++) { ObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[b]; ObjectMovementUpdate objectupdate = new ObjectMovementUpdate(); //Vector4 collisionPlane = Vector4.Zero; //Vector3 position; //Vector3 velocity; //Vector3 acceleration; //Quaternion rotation; //Vector3 angularVelocity; NameValue[] nameValues; bool attachment = false; PCode pcode = (PCode)block.PCode; #region Relevance check // Check if we are interested in this object if (!Client.Settings.ALWAYS_DECODE_OBJECTS) { switch (pcode) { case PCode.Grass: case PCode.Tree: case PCode.NewTree: case PCode.Prim: if (m_ObjectUpdate == null) continue; break; case PCode.Avatar: // Make an exception for updates about our own agent if (block.FullID != Client.Self.AgentID && m_AvatarUpdate == null) continue; break; case PCode.ParticleSystem: continue; // TODO: Do something with these } } #endregion Relevance check #region NameValue parsing string nameValue = Utils.BytesToString(block.NameValue); if (nameValue.Length > 0) { string[] lines = nameValue.Split('\n'); nameValues = new NameValue[lines.Length]; for (int i = 0; i < lines.Length; i++) { if (!String.IsNullOrEmpty(lines[i])) { NameValue nv = new NameValue(lines[i]); if (nv.Name == "AttachItemID") attachment = true; nameValues[i] = nv; } } } else { nameValues = new NameValue[0]; } #endregion NameValue parsing #region Decode Object (primitive) parameters Primitive.ConstructionData data = new Primitive.ConstructionData(); data.State = block.State; data.Material = (Material)block.Material; data.PathCurve = (PathCurve)block.PathCurve; data.profileCurve = block.ProfileCurve; data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin); data.PathEnd = Primitive.UnpackEndCut(block.PathEnd); data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX); data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY); data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX); data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY); data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist); data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin); data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset); data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX); data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY); data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions); data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew); data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin); data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd); data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); data.PCode = pcode; #endregion #region Decode Additional packed parameters in ObjectData int pos = 0; switch (block.ObjectData.Length) { case 76: // Collision normal for avatar objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos); pos += 16; goto case 60; case 60: // Position objectupdate.Position = new Vector3(block.ObjectData, pos); pos += 12; // Velocity objectupdate.Velocity = new Vector3(block.ObjectData, pos); pos += 12; // Acceleration objectupdate.Acceleration = new Vector3(block.ObjectData, pos); pos += 12; // Rotation (theta) objectupdate.Rotation = new Quaternion(block.ObjectData, pos, true); pos += 12; // Angular velocity (omega) objectupdate.AngularVelocity = new Vector3(block.ObjectData, pos); pos += 12; break; case 48: // Collision normal for avatar objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos); pos += 16; goto case 32; case 32: // The data is an array of unsigned shorts // Position objectupdate.Position = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -0.5f * 256.0f, 1.5f * 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -0.5f * 256.0f, 1.5f * 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 3.0f * 256.0f)); pos += 6; // Velocity objectupdate.Velocity = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; // Acceleration objectupdate.Acceleration = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; // Rotation (theta) objectupdate.Rotation = new Quaternion( Utils.UInt16ToFloat(block.ObjectData, pos, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 6, -1.0f, 1.0f)); pos += 8; // Angular velocity (omega) objectupdate.AngularVelocity = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; break; case 16: // The data is an array of single bytes (8-bit numbers) // Position objectupdate.Position = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Velocity objectupdate.Velocity = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Accleration objectupdate.Acceleration = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Rotation objectupdate.Rotation = new Quaternion( Utils.ByteToFloat(block.ObjectData, pos, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 3, -1.0f, 1.0f)); pos += 4; // Angular Velocity objectupdate.AngularVelocity = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; break; default: Logger.Log("Got an ObjectUpdate block with ObjectUpdate field length of " + block.ObjectData.Length, Helpers.LogLevel.Warning, Client); continue; } #endregion // Determine the object type and create the appropriate class switch (pcode) { #region Prim and Foliage case PCode.Grass: case PCode.Tree: case PCode.NewTree: case PCode.Prim: bool isNewObject; lock (simulator.ObjectsPrimitives.Dictionary) isNewObject = !simulator.ObjectsPrimitives.ContainsKey(block.ID); Primitive prim = GetPrimitive(simulator, block.ID, block.FullID); // Textures objectupdate.Textures = new Primitive.TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); OnObjectDataBlockUpdate(new ObjectDataBlockUpdateEventArgs(simulator, prim, data, block, objectupdate, nameValues)); #region Update Prim Info with decoded data prim.Flags = (PrimFlags)block.UpdateFlags; if ((prim.Flags & PrimFlags.ZlibCompressed) != 0) { Logger.Log("Got a ZlibCompressed ObjectUpdate, implement me!", Helpers.LogLevel.Warning, Client); continue; } // Automatically request ObjectProperties for prim if it was rezzed selected. if ((prim.Flags & PrimFlags.CreateSelected) != 0) { SelectObject(simulator, prim.LocalID); } prim.NameValues = nameValues; prim.LocalID = block.ID; prim.ID = block.FullID; prim.ParentID = block.ParentID; prim.RegionHandle = update.RegionData.RegionHandle; prim.Scale = block.Scale; prim.ClickAction = (ClickAction)block.ClickAction; prim.OwnerID = block.OwnerID; prim.MediaURL = Utils.BytesToString(block.MediaURL); prim.Text = Utils.BytesToString(block.Text); prim.TextColor = new Color4(block.TextColor, 0, false, true); // Sound information prim.Sound = block.Sound; prim.SoundFlags = (SoundFlags)block.Flags; prim.SoundGain = block.Gain; prim.SoundRadius = block.Radius; // Joint information prim.Joint = (JointType)block.JointType; prim.JointPivot = block.JointPivot; prim.JointAxisOrAnchor = block.JointAxisOrAnchor; // Object parameters prim.PrimData = data; // Textures, texture animations, particle system, and extra params prim.Textures = objectupdate.Textures; prim.TextureAnim = new Primitive.TextureAnimation(block.TextureAnim, 0); prim.ParticleSys = new Primitive.ParticleSystem(block.PSBlock, 0); prim.SetExtraParamsFromBytes(block.ExtraParams, 0); // PCode-specific data switch (pcode) { case PCode.Grass: case PCode.Tree: case PCode.NewTree: if (block.Data.Length == 1) prim.TreeSpecies = (Tree)block.Data[0]; else Logger.Log("Got a foliage update with an invalid TreeSpecies field", Helpers.LogLevel.Warning); // prim.ScratchPad = Utils.EmptyBytes; // break; //default: // prim.ScratchPad = new byte[block.Data.Length]; // if (block.Data.Length > 0) // Buffer.BlockCopy(block.Data, 0, prim.ScratchPad, 0, prim.ScratchPad.Length); break; } prim.ScratchPad = Utils.EmptyBytes; // Packed parameters prim.CollisionPlane = objectupdate.CollisionPlane; prim.Position = objectupdate.Position; prim.Velocity = objectupdate.Velocity; prim.Acceleration = objectupdate.Acceleration; prim.Rotation = objectupdate.Rotation; prim.AngularVelocity = objectupdate.AngularVelocity; #endregion OnObjectUpdate(new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNewObject, attachment)); break; #endregion Prim and Foliage #region Avatar case PCode.Avatar: bool isNewAvatar; lock (simulator.ObjectsAvatars.Dictionary) isNewAvatar = !simulator.ObjectsAvatars.ContainsKey(block.ID); // Update some internals if this is our avatar if (block.FullID == Client.Self.AgentID && simulator == Client.Network.CurrentSim) { #region Update Client.Self // We need the local ID to recognize terse updates for our agent Client.Self.localID = block.ID; // Packed parameters Client.Self.collisionPlane = objectupdate.CollisionPlane; Client.Self.relativePosition = objectupdate.Position; Client.Self.velocity = objectupdate.Velocity; Client.Self.acceleration = objectupdate.Acceleration; Client.Self.relativeRotation = objectupdate.Rotation; Client.Self.angularVelocity = objectupdate.AngularVelocity; #endregion } #region Create an Avatar from the decoded data Avatar avatar = GetAvatar(simulator, block.ID, block.FullID); objectupdate.Avatar = true; // Textures objectupdate.Textures = new Primitive.TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); OnObjectDataBlockUpdate(new ObjectDataBlockUpdateEventArgs(simulator, avatar, data, block, objectupdate, nameValues)); uint oldSeatID = avatar.ParentID; avatar.ID = block.FullID; avatar.LocalID = block.ID; avatar.CollisionPlane = objectupdate.CollisionPlane; avatar.Position = objectupdate.Position; avatar.Velocity = objectupdate.Velocity; avatar.Acceleration = objectupdate.Acceleration; avatar.Rotation = objectupdate.Rotation; avatar.AngularVelocity = objectupdate.AngularVelocity; avatar.NameValues = nameValues; avatar.PrimData = data; if (block.Data.Length > 0) { Logger.Log("Unexpected Data field for an avatar update, length " + block.Data.Length, Helpers.LogLevel.Warning); } avatar.ParentID = block.ParentID; avatar.RegionHandle = update.RegionData.RegionHandle; SetAvatarSittingOn(simulator, avatar, block.ParentID, oldSeatID); // Textures avatar.Textures = objectupdate.Textures; #endregion Create an Avatar from the decoded data OnAvatarUpdate(new AvatarUpdateEventArgs(simulator, avatar, update.RegionData.TimeDilation, isNewAvatar)); break; #endregion Avatar case PCode.ParticleSystem: DecodeParticleUpdate(block); // TODO: Create a callback for particle updates break; default: Logger.DebugLog("Got an ObjectUpdate block with an unrecognized PCode " + pcode.ToString(), Client); break; } } }
/// <summary> /// [05:31] <AFrisby> dmiles_afk, search my blog, I wrote a function for converting OpenMetaverse.Primitive to OpenSimulator.SceneObjectGroup /// /// from: http://www.adamfrisby.com/blog/2008/10/code-snippet-converting-openmetaverseprimitive-to-opensimulatorsceneobjectpart/ /// </summary> /// <param name="orig"></param> /// <returns></returns> static public PrimitiveBaseShape PrimToBaseShape(Primitive orig) { //bool root = orig.ParentID == 0; //SceneObjectPart sop = new SceneObjectPart(); //sop.LastOwnerID = orig.OwnerID; //sop.OwnerID = orig.OwnerID; //sop.GroupID = orig.GroupID; //sop.CreatorID = orig.Properties.CreatorID; //sop.OwnershipCost = orig.Properties.OwnershipCost; //sop.ObjectSaleType = (byte)orig.Properties.SaleType; //sop.SalePrice = orig.Properties.SalePrice; //sop.CreationDate = (int)Utils.DateTimeToUnixTime(orig.Properties.CreationDate); //// Special //sop.ParentID = 0; //sop.OwnerMask = (uint)orig.Properties.Permissions.OwnerMask; //sop.NextOwnerMask = (uint)orig.Properties.Permissions.NextOwnerMask; //sop.GroupMask = (uint)orig.Properties.Permissions.GroupMask; //sop.EveryoneMask = (uint)orig.Properties.Permissions.EveryoneMask; //sop.BaseMask = (uint)orig.Properties.Permissions.BaseMask; //sop.ParticleSystem = orig.ParticleSys.GetBytes(); //// OS only //sop.TimeStampFull = 0; //sop.TimeStampLastActivity = 0; //sop.TimeStampTerse = 0; //// Not sure nessecary //sop.UpdateFlag = 2; //sop.InventorySerial = 0; //sop.UUID = orig.ID; //sop.LocalId = orig.LocalID; //sop.Name = orig.Properties.Name; //sop.Flags = orig.Flags; //sop.Material = 0; //sop.RegionHandle = orig.RegionHandle; //sop.GroupPosition = orig.Position; //if (!root) // sop.OffsetPosition = orig.Position; //else // sop.OffsetPosition = Vector3.Zero; //sop.RotationOffset = orig.Rotation; //sop.Velocity = orig.Velocity; //sop.RotationalVelocity = Vector3.Zero; //sop.AngularVelocity = Vector3.Zero; //sop.Acceleration = Vector3.Zero; //sop.Description = orig.Properties.Description; //sop.Color = Color.White; //sop.Text = orig.Text; //sop.SitName = orig.Properties.SitName; //sop.TouchName = orig.Properties.TouchName; //sop.ClickAction = (byte)orig.ClickAction; //sop.PayPrice = new int[1]; PrimitiveBaseShape sopShape = new PrimitiveBaseShape(true); //sopShape.Scale = orig.Scale; sopShape.FlexiEntry = false; if (orig.Flexible != null) { sopShape.FlexiDrag = orig.Flexible.Drag; sopShape.FlexiEntry = false; sopShape.FlexiForceX = orig.Flexible.Force.X; sopShape.FlexiForceY = orig.Flexible.Force.Y; sopShape.FlexiForceZ = orig.Flexible.Force.Z; sopShape.FlexiGravity = orig.Flexible.Gravity; sopShape.FlexiSoftness = orig.Flexible.Softness; sopShape.FlexiTension = orig.Flexible.Tension; sopShape.FlexiWind = orig.Flexible.Wind; } Primitive.ConstructionData origPrimData = orig.PrimData; switch (origPrimData.ProfileHole) { case HoleType.Circle: sopShape.HollowShape = HollowShape.Circle; break; case HoleType.Square: sopShape.HollowShape = HollowShape.Square; break; case HoleType.Triangle: sopShape.HollowShape = HollowShape.Triangle; break; default: case HoleType.Same: sopShape.HollowShape = HollowShape.Same; break; } sopShape.LightEntry = false; if (orig.Light != null) { sopShape.LightColorA = orig.Light.Color.A; sopShape.LightColorB = orig.Light.Color.B; sopShape.LightColorG = orig.Light.Color.G; sopShape.LightColorR = orig.Light.Color.R; sopShape.LightCutoff = orig.Light.Cutoff; sopShape.LightEntry = false; sopShape.LightFalloff = orig.Light.Falloff; sopShape.LightIntensity = orig.Light.Intensity; sopShape.LightRadius = orig.Light.Radius; } sopShape.PathBegin = Primitive.PackBeginCut(origPrimData.PathBegin); sopShape.PathCurve = (byte)origPrimData.PathCurve; sopShape.PathEnd = Primitive.PackEndCut(origPrimData.PathEnd); sopShape.PathRadiusOffset = Primitive.PackPathTwist(origPrimData.PathRadiusOffset); sopShape.PathRevolutions = Primitive.PackPathRevolutions(origPrimData.PathRevolutions); sopShape.PathScaleX = Primitive.PackPathScale(origPrimData.PathScaleX); sopShape.PathScaleY = Primitive.PackPathScale(origPrimData.PathScaleY); sopShape.PathShearX = (byte)Primitive.PackPathShear(origPrimData.PathShearX); sopShape.PathShearY = (byte)Primitive.PackPathShear(origPrimData.PathShearY); sopShape.PathSkew = Primitive.PackPathTwist(origPrimData.PathSkew); sopShape.PathTaperX = Primitive.PackPathTaper(origPrimData.PathTaperX); sopShape.PathTaperY = Primitive.PackPathTaper(origPrimData.PathTaperY); sopShape.PathTwist = Primitive.PackPathTwist(origPrimData.PathTwist); sopShape.PathTwistBegin = Primitive.PackPathTwist(origPrimData.PathTwistBegin); sopShape.PCode = (byte)origPrimData.PCode; sopShape.ProfileBegin = Primitive.PackBeginCut(origPrimData.ProfileBegin); sopShape.ProfileCurve = origPrimData.profileCurve; sopShape.ProfileEnd = Primitive.PackEndCut(origPrimData.ProfileEnd); sopShape.ProfileHollow = Primitive.PackProfileHollow(origPrimData.ProfileHollow); sopShape.ProfileShape = (ProfileShape)(byte)origPrimData.ProfileCurve; sopShape.Textures = orig.Textures; return(sopShape); }
static void Main(string[] args) { if (args.Length != 8 && args.Length != 9) { Console.WriteLine("Usage: importprimscript.exe [firstname] [lastname] [password] " + "[loginuri] [Simulator] [x] [y] [z] [input.primscript]" + Environment.NewLine + "Example: importprimscript.exe My Bot password " + "Hooper 128 128 40 maya-export" + Path.DirectorySeparatorChar + "ant.primscript" + Environment.NewLine + "(the loginuri is optional and only used for logging in to another grid)"); Environment.Exit(-1); } // Strip quotes from any arguments for (int i = 0; i < args.Length; i++) args[i] = args[i].Trim(new char[] { '"' }); // Parse the primscript file string scriptfilename = args[args.Length - 1]; string error; List<Sculpt> sculpties = ParsePrimscript(scriptfilename, out error); scriptfilename = Path.GetFileNameWithoutExtension(scriptfilename); // Check for parsing errors if (error != String.Empty) { Console.WriteLine("An error was encountered reading the input file: " + error); Environment.Exit(-2); } else if (sculpties.Count == 0) { Console.WriteLine("No primitives were read from the input file"); Environment.Exit(-3); } // Add callback handlers for asset uploads finishing. new prims spotted, and logging Client.Objects.ObjectUpdate += new EventHandler<PrimEventArgs>(Objects_OnNewPrim); Logger.OnLogMessage += new Logger.LogCallback(Client_OnLogMessage); // Optimize the connection for our purposes Client.Self.Movement.Camera.Far = 64f; Client.Settings.MULTIPLE_SIMS = false; Client.Settings.SEND_AGENT_UPDATES = true; Settings.LOG_LEVEL = Helpers.LogLevel.None; Client.Settings.ALWAYS_REQUEST_OBJECTS = true; Client.Settings.ALWAYS_DECODE_OBJECTS = true; Client.Settings.THROTTLE_OUTGOING_PACKETS = false; Client.Throttle.Land = 0; Client.Throttle.Wind = 0; Client.Throttle.Cloud = 0; // Not sure if Asset or Texture will help with uploads, but it won't hurt Client.Throttle.Asset = 220000.0f; Client.Throttle.Texture = 446000.0f; Client.Throttle.Task = 446000.0f; // Create a handler for the event queue connecting, so we know when // it is safe to start uploading AutoResetEvent eventQueueEvent = new AutoResetEvent(false); EventHandler<EventQueueRunningEventArgs> eventQueueCallback = delegate(object sender, EventQueueRunningEventArgs e) { if (e.Simulator == Client.Network.CurrentSim) eventQueueEvent.Set(); }; Client.Network.EventQueueRunning += eventQueueCallback; int x = Int32.Parse(args[args.Length - 4]); int y = Int32.Parse(args[args.Length - 3]); int z = Int32.Parse(args[args.Length - 2]); string start = NetworkManager.StartLocation(args[args.Length - 5], x, y, z); LoginParams loginParams = Client.Network.DefaultLoginParams(args[0], args[1], args[2], "importprimscript", "1.4.0"); loginParams.Start = start; if (args.Length == 9) loginParams.URI = args[3]; // Attempt to login if (!Client.Network.Login(loginParams)) { Console.WriteLine("Login failed: " + Client.Network.LoginMessage); Environment.Exit(-4); } // Need to be connected to the event queue before we can upload Console.WriteLine("Login succeeded, waiting for the event handler to connect..."); if (!eventQueueEvent.WaitOne(1000 * 90, false)) { Console.WriteLine("Event queue connection timed out, disconnecting..."); Client.Network.Logout(); Environment.Exit(-5); } // Don't need this anymore Client.Network.EventQueueRunning -= eventQueueCallback; // Set the root position for the import RootPosition = Client.Self.SimPosition; RootPosition.Z += 3.0f; // TODO: Check if our account balance is high enough to upload everything // // Create a folder to hold all of our texture uploads UploadFolderID = Client.Inventory.CreateFolder(Client.Inventory.Store.RootFolder.UUID, scriptfilename); // Loop through each sculpty and do what we need to do for (int i = 0; i < sculpties.Count; i++) { // Upload the sculpt map and texture sculpties[i].SculptID = UploadImage(sculpties[i].SculptFile, true); sculpties[i].TextureID = UploadImage(sculpties[i].TextureFile, false); // Check for failed uploads if (sculpties[i].SculptID == UUID.Zero) { Console.WriteLine("Sculpt map " + sculpties[i].SculptFile + " failed to upload, skipping " + sculpties[i].Name); continue; } else if (sculpties[i].TextureID == UUID.Zero) { Console.WriteLine("Texture " + sculpties[i].TextureFile + " failed to upload, skipping " + sculpties[i].Name); continue; } // Create basic spherical volume parameters. It will be set to // a scultpy in the callback for new objects being created Primitive.ConstructionData volume = new Primitive.ConstructionData(); volume.PCode = PCode.Prim; volume.Material = Material.Wood; volume.PathScaleY = 0.5f; volume.PathCurve = PathCurve.Circle; volume.ProfileCurve = ProfileCurve.Circle; // Rez this prim CurrentSculpt = sculpties[i]; Client.Objects.AddPrim(Client.Network.CurrentSim, volume, UUID.Zero, RootPosition + CurrentSculpt.Offset, CurrentSculpt.Scale, Quaternion.Identity); // Wait for the prim to rez and the properties be set for it if (!RezzedEvent.WaitOne(1000 * 10, false)) { Console.WriteLine("Timed out waiting for prim " + CurrentSculpt.Name + " to rez, skipping"); continue; } } CurrentSculpt = null; lock (RezzedPrims) { // Set full permissions for all of the objects Client.Objects.SetPermissions(Client.Network.CurrentSim, RezzedPrims, PermissionWho.All, PermissionMask.All, true); // Link the entire object together Client.Objects.LinkPrims(Client.Network.CurrentSim, RezzedPrims); } Console.WriteLine("Rezzed, textured, and linked " + RezzedPrims.Count + " sculpted prims, logging out..."); Client.Network.Logout(); }
public Primitive AddTempPrim(SimRegion R, string name, PrimType primType, Vector3 scale, Vector3 loc) { Primitive.ConstructionData CD = ObjectManager.BuildBasicShape(primType); CD.Material = Material.Light; CD.ProfileHole = HoleType.Triangle; bool success = false; Simulator simulator = R.TheSimulator; Primitive newPrim = null; // Register a handler for the creation event AutoResetEvent creationEvent = new AutoResetEvent(false); Quaternion rot = Quaternion.Identity; EventHandler <PrimEventArgs> callback = (s, e) =>//delegate(Simulator simulator0, Primitive prim, ulong regionHandle, ushort timeDilation) { var regionHandle = e.Simulator.Handle; var prim = e.Prim; if (regionHandle != R.RegionHandle) { return; } if ((loc - prim.Position).Length() > 3) { Debug("Not the prim " + (loc - prim.Position).Length()); return; } if (prim.PrimData.ProfileHole != HoleType.Triangle) { Debug("Not the prim? prim.PrimData.ProfileHole != HoleType.Triangle: {0}!={1}", prim.PrimData.ProfileHole, HoleType.Triangle); // return; // } if (Material.Light != prim.PrimData.Material) { Debug("Not the prim? Material.Light != prim.PrimData.Material: {0}!={1}", Material.Light, prim.PrimData.Material); // return; } if ((prim.Flags & PrimFlags.CreateSelected) == 0) { Debug("Not the prim? (prim.Flags & PrimFlags.CreateSelected) == 0) was {0}", prim.Flags); // return; } if (primType != prim.Type) { Debug("Not the prim? Material.Light != prim.PrimData.Material: {0}!={1}", Material.Light, prim.PrimData.Material); // return; } //if (prim.Scale != scale) return; // if (prim.Rotation != rot) return; // if (Material.Light != prim.PrimData.Material) return; //if (CD != prim.PrimData) return; newPrim = prim; creationEvent.Set(); }; client.Objects.ObjectUpdate += callback; // Start the creation setting process (with baking enabled or disabled) client.Objects.AddPrim(simulator, CD, UUID.Zero, loc, scale, rot, PrimFlags.CreateSelected | PrimFlags.Phantom | PrimFlags.Temporary); // Wait for the process to complete or time out if (creationEvent.WaitOne(1000 * 120, false)) { success = true; } // Unregister the handler client.Objects.ObjectUpdate -= callback; // Return success or failure message if (!success) { Debug("Timeout on new prim " + name); return(null); } uint LocalID = newPrim.LocalID; client.Objects.SetName(simulator, LocalID, name); client.Objects.SetPosition(simulator, LocalID, loc); client.Objects.SetScale(simulator, LocalID, scale, true, true); client.Objects.SetRotation(simulator, LocalID, rot); client.Objects.SetFlags(simulator, LocalID, false, true, true, false); return(newPrim); }
public OSDMap GetOSD() { Primitive.ConstructionData primData = Prim.PrimData; Primitive.ObjectProperties properties = Prim.Properties; OSDMap pathMap = new OSDMap(); pathMap["begin"] = OSD.FromReal(primData.PathBegin); pathMap["curve"] = OSD.FromInteger((int)primData.PathCurve); pathMap["end"] = OSD.FromReal(primData.PathEnd); pathMap["radius_offset"] = OSD.FromReal(primData.PathRadiusOffset); pathMap["revolutions"] = OSD.FromReal(primData.PathRevolutions); pathMap["scale_x"] = OSD.FromReal(primData.PathScaleX); pathMap["scale_y"] = OSD.FromReal(primData.PathScaleY); pathMap["shear_x"] = OSD.FromReal(primData.PathShearX); pathMap["shear_y"] = OSD.FromReal(primData.PathShearY); pathMap["skew"] = OSD.FromReal(primData.PathSkew); pathMap["taper_x"] = OSD.FromReal(primData.PathTaperX); pathMap["taper_y"] = OSD.FromReal(primData.PathTaperY); pathMap["twist"] = OSD.FromReal(primData.PathTwist); pathMap["twist_begin"] = OSD.FromReal(primData.PathTwistBegin); OSDMap profileMap = new OSDMap(); profileMap["begin"] = OSD.FromReal(primData.ProfileBegin); profileMap["curve"] = OSD.FromInteger((int)primData.ProfileCurve); profileMap["hole"] = OSD.FromInteger((int)primData.ProfileHole); profileMap["end"] = OSD.FromReal(primData.ProfileEnd); profileMap["hollow"] = OSD.FromReal(primData.ProfileHollow); OSDMap propertiesMap = new OSDMap(); if (properties != null) { propertiesMap["aggregate_perms"] = OSD.FromInteger(properties.AggregatePerms); propertiesMap["aggregate_perms_textures"] = OSD.FromInteger(properties.AggregatePermTextures); propertiesMap["aggregate_perms_textures_owner"] = OSD.FromInteger(properties.AggregatePermTexturesOwner); propertiesMap["category"] = OSD.FromInteger((int)properties.Category); propertiesMap["creation_date"] = OSD.FromDate(properties.CreationDate); propertiesMap["creator_id"] = OSD.FromUUID(properties.CreatorID); propertiesMap["description"] = OSD.FromString(properties.Description); propertiesMap["folder_id"] = OSD.FromUUID(properties.FolderID); propertiesMap["from_task_id"] = OSD.FromUUID(properties.FromTaskID); // properties.GroupID is redundant propertiesMap["inventory_serial"] = OSD.FromInteger(properties.InventorySerial); propertiesMap["item_id"] = OSD.FromUUID(properties.ItemID); propertiesMap["last_owner_id"] = OSD.FromUUID(properties.LastOwnerID); propertiesMap["name"] = OSD.FromString(properties.Name); // properties.ObjectID is redundant // properties.OwnerID is redundant propertiesMap["ownership_cost"] = OSD.FromInteger(properties.OwnershipCost); propertiesMap["permissions"] = properties.Permissions.GetOSD(); propertiesMap["sale_price"] = OSD.FromInteger(properties.SalePrice); propertiesMap["sale_type"] = OSD.FromInteger((int)properties.SaleType); propertiesMap["sit_name"] = OSD.FromString(properties.SitName); propertiesMap["touch_name"] = OSD.FromString(properties.TouchName); } OSDMap primMap = new OSDMap(); primMap["path"] = pathMap; primMap["profile"] = profileMap; primMap["properties"] = propertiesMap; primMap["acceleration"] = OSD.FromVector3(Prim.Acceleration); primMap["ang_velocity"] = OSD.FromVector3(Prim.AngularVelocity); primMap["click_action"] = OSD.FromInteger((int)Prim.ClickAction); primMap["flags"] = OSD.FromInteger((uint)Prim.Flags); primMap["group_id"] = OSD.FromUUID(Prim.GroupID); primMap["id"] = OSD.FromUUID(Prim.ID); primMap["local_id"] = OSD.FromInteger(Prim.LocalID); primMap["media_url"] = OSD.FromString(Prim.MediaURL); primMap["owner_id"] = OSD.FromUUID(Prim.OwnerID); primMap["parent_id"] = OSD.FromInteger(Prim.ParentID); primMap["particles"] = Prim.ParticleSys.GetOSD(); primMap["position"] = OSD.FromVector3(Prim.Position); primMap["rotation"] = OSD.FromQuaternion(Prim.Rotation); primMap["scale"] = OSD.FromVector3(Prim.Scale); primMap["scratch_pad"] = OSD.FromBinary(Prim.ScratchPad); primMap["sound"] = OSD.FromUUID(Prim.Sound); primMap["sound_flags"] = OSD.FromInteger((int)Prim.SoundFlags); primMap["sound_gain"] = OSD.FromReal(Prim.SoundGain); primMap["sound_radius"] = OSD.FromReal(Prim.SoundRadius); primMap["text"] = OSD.FromString(Prim.Text); primMap["text_color"] = OSD.FromColor4(Prim.TextColor); primMap["texture_anim"] = Prim.TextureAnim.GetOSD(); primMap["tree_species"] = OSD.FromInteger((int)Prim.TreeSpecies); primMap["velocity"] = OSD.FromVector3(Prim.Velocity); primMap["material"] = OSD.FromInteger((int)primData.Material); primMap["state"] = OSD.FromInteger(primData.State); primMap["pcode"] = OSD.FromInteger((int)primData.PCode); if (Prim.NameValues != null) primMap["name_values"] = OSD.FromString(NameValue.NameValuesToString(Prim.NameValues)); if (Prim.Textures != null) primMap["textures"] = Prim.Textures.GetOSD(); if (Prim.Light != null) primMap["light"] = Prim.Light.GetOSD(); if (Prim.Flexible != null) primMap["flex"] = Prim.Flexible.GetOSD(); if (Prim.Sculpt != null) primMap["sculpt"] = Prim.Sculpt.GetOSD(); OSDMap map = new OSDMap(); map["prim"] = primMap; map["sit_position"] = OSD.FromVector3(SitPosition); map["sit_rotation"] = OSD.FromQuaternion(SitRotation); map["attachment_position"] = OSD.FromVector3(AttachmentPosition); map["attachment_rotation"] = OSD.FromQuaternion(AttachmentRotation); map["last_attachment_point"] = OSD.FromInteger((int)LastAttachmentPoint); map["before_attachment_rotation"] = OSD.FromQuaternion(BeforeAttachmentRotation); map["rotation_axis"] = OSD.FromVector3(m_rotationAxis); map["link_number"] = OSD.FromInteger(m_linkNumber); map["remote_script_access_pin"] = OSD.FromInteger(RemoteScriptAccessPIN); map["inventory"] = OSD.FromString(Inventory.GetTaskInventoryAsset()); OSDArray buttons = new OSDArray { OSD.FromInteger(PayPriceButtons[0]), OSD.FromInteger(PayPriceButtons[1]), OSD.FromInteger(PayPriceButtons[2]), OSD.FromInteger(PayPriceButtons[3]) }; map["pay_price_buttons"] = buttons; map["pay_price"] = OSD.FromInteger(PayPrice); if (Prim.FaceMedia != null) { OSDArray faceMedia = new OSDArray(Prim.FaceMedia.Length); for (int i = 0; i < Prim.FaceMedia.Length; i++) { MediaEntry entry = Prim.FaceMedia[i]; if (entry != null) faceMedia.Add(entry.GetOSD()); else faceMedia.Add(new OSD()); } map["face_media"] = faceMedia; } map["media_version"] = OSD.FromString(Prim.MediaVersion); map["last_updated"] = OSD.FromDate(m_lastUpdated); return map; }
private void SetPrimType(IScriptInstance script, object[] rules, ref int i) { LLPrimitive prim = script.Host as LLPrimitive; if (prim == null) { return; } int code = llList2Integer(script, rules, i++); switch (code) { case LSLConstants.PRIM_TYPE_BOX: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Box); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear); break; } case LSLConstants.PRIM_TYPE_CYLINDER: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Cylinder); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear); break; } case LSLConstants.PRIM_TYPE_PRISM: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Prism); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear); break; } case LSLConstants.PRIM_TYPE_SPHERE: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 dimple = llList2Vector(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Sphere); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, dimple); break; } case LSLConstants.PRIM_TYPE_TORUS: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Vector3 advCut = llList2Vector(script, rules, i++); Vector3 taper = llList2Vector(script, rules, i++); float revolutions = llList2Float(script, rules, i++); float radiusOffset = llList2Float(script, rules, i++); float skew = llList2Float(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Torus); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear, advCut, taper, revolutions, radiusOffset, skew); break; } case LSLConstants.PRIM_TYPE_TUBE: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Vector3 advCut = llList2Vector(script, rules, i++); Vector3 taper = llList2Vector(script, rules, i++); float revolutions = llList2Float(script, rules, i++); float radiusOffset = llList2Float(script, rules, i++); float skew = llList2Float(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Tube); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear, advCut, taper, revolutions, radiusOffset, skew); break; } case LSLConstants.PRIM_TYPE_RING: { int holeShape = llList2Integer(script, rules, i++); Vector3 cut = llList2Vector(script, rules, i++); float hollow = llList2Float(script, rules, i++); Vector3 twist = llList2Vector(script, rules, i++); Vector3 topSize = llList2Vector(script, rules, i++); Vector3 topShear = llList2Vector(script, rules, i++); Vector3 advCut = llList2Vector(script, rules, i++); Vector3 taper = llList2Vector(script, rules, i++); float revolutions = llList2Float(script, rules, i++); float radiusOffset = llList2Float(script, rules, i++); float skew = llList2Float(script, rules, i++); Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Ring); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; prim.Prim.PrimData = primData; prim.Prim.Sculpt = null; SetPrimShapeParams(prim, holeShape, cut, hollow, twist, topSize, topShear, advCut, taper, revolutions, radiusOffset, skew); break; } case LSLConstants.PRIM_TYPE_SCULPT: { string sculptMap = llList2String(script, rules, i++); SculptType type = (SculptType)llList2Integer(script, rules, i++); UUID textureID = InventoryKey(script, sculptMap, AssetType.Texture); if (textureID == UUID.Zero) { return; } Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(PrimType.Sculpt); primData.Material = prim.Prim.PrimData.Material; primData.State = prim.Prim.PrimData.State; Primitive.SculptData sculpt = new Primitive.SculptData(); sculpt.Type = type; sculpt.SculptTexture = textureID; prim.Prim.PrimData = primData; prim.Prim.Sculpt = sculpt; break; } } }
// from IdealistViewer.PrimMesherG.cs public PrimMesh ConstructionDataToPrimMesh(Primitive.ConstructionData primData, LevelOfDetail detail, float detailMult) { this.sides = 4; this.hollowsides = 4; float profileBegin = primData.ProfileBegin; float profileEnd = primData.ProfileEnd; bool isSphere = false; if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.Circle) { switch (detail) { case LevelOfDetail.Low: sides = 6; break; case LevelOfDetail.Medium: sides = 12; break; default: sides = 24; break; } } else if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.EqualTriangle) { sides = 3; } else if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.HalfCircle) { // half circle, prim is a sphere isSphere = true; switch (detail) { case LevelOfDetail.Low: sides = 6; break; case LevelOfDetail.Medium: sides = 12; break; default: sides = 24; break; } profileBegin = 0.5f * profileBegin + 0.5f; profileEnd = 0.5f * profileEnd + 0.5f; } if ((HoleType)primData.ProfileHole == HoleType.Same) { hollowsides = sides; } else if ((HoleType)primData.ProfileHole == HoleType.Circle) { switch (detail) { case LevelOfDetail.Low: hollowsides = 6; break; case LevelOfDetail.Medium: hollowsides = 12; break; default: hollowsides = 24; break; } } else if ((HoleType)primData.ProfileHole == HoleType.Triangle) { hollowsides = 3; } // if (UseExtremeDetail) { sides = (int)(sides * detailMult); hollowsides = (int)(hollowsides * detailMult); } PrimMesh primMesh = new PrimMesh(sides, profileBegin, profileEnd, (float)primData.ProfileHollow, hollowsides); primMesh.viewerMode = UseViewerMode; primMesh.holeSizeX = primData.PathScaleX; primMesh.holeSizeY = primData.PathScaleY; primMesh.pathCutBegin = primData.PathBegin; primMesh.pathCutEnd = primData.PathEnd; primMesh.topShearX = primData.PathShearX; primMesh.topShearY = primData.PathShearY; primMesh.radius = primData.PathRadiusOffset; primMesh.revolutions = primData.PathRevolutions; primMesh.skew = primData.PathSkew; switch (detail) { case LevelOfDetail.Low: primMesh.stepsPerRevolution = 6; break; case LevelOfDetail.Medium: primMesh.stepsPerRevolution = 12; break; default: primMesh.stepsPerRevolution = 24; break; } //if (UseExtremeDetail) { primMesh.stepsPerRevolution = (int)(primMesh.stepsPerRevolution * detailMult); } if (primData.PathCurve == PathCurve.Line) { primMesh.taperX = 1.0f - primData.PathScaleX; primMesh.taperY = 1.0f - primData.PathScaleY; primMesh.twistBegin = (int)(180 * primData.PathTwistBegin); primMesh.twistEnd = (int)(180 * primData.PathTwist); primMesh.ExtrudeLinear(); } else { primMesh.taperX = primData.PathTaperX; primMesh.taperY = primData.PathTaperY; primMesh.twistBegin = (int)(360 * primData.PathTwistBegin); primMesh.twistEnd = (int)(360 * primData.PathTwist); primMesh.ExtrudeCircular(); } if (UseViewerMode) { int numViewerFaces = primMesh.viewerFaces.Count; for (uint i = 0; i < numViewerFaces; i++) { ViewerFace vf = primMesh.viewerFaces[(int)i]; if (isSphere) { vf.uv1.U = (vf.uv1.U - 0.5f) * 2.0f; vf.uv2.U = (vf.uv2.U - 0.5f) * 2.0f; vf.uv3.U = (vf.uv3.U - 0.5f) * 2.0f; } } } return(primMesh); }
private void PrimtiveBlockUpdate(Simulator simulator, ObjectMovementUpdate objectupdate0, Primitive prim, ObjectUpdatePacket.ObjectDataBlock block, Primitive.ConstructionData data) { bool isNewPrim = prim.Scale == Vector3.Zero && prim.Position == Vector3.Zero && prim.NameValues == null; if (prim.ID == UUID.Zero) { if (!simulator.Client.Settings.OBJECT_TRACKING) { throw new ArgumentException("Need to enable object tracking!!"); } SimObject O = GetSimObjectFromUUID(block.FullID); if (O == null) { Debug("PrimData ZERO for " + prim); if (block.ID > 0) { uint localID = block.ID; prim.LocalID = localID; prim.ID = block.FullID; // var p = simulator.Client.Objects.GetPrimitive(simulator, block.ID, block.FullID, false); // simulator.GetPrimitive( } } else { Debug("SimData ZERO for " + prim); uint localID = block.ID; prim.LocalID = localID; prim.ID = block.FullID; O.IsDebugging = true; } } // else { if (prim.RegionHandle == simulator.Handle && prim.ID != UUID.Zero) { if (!prim.PrimData.Equals(data) /* || prim.Scale != block.Scale || prim.Position != objectupdate.Position || prim.Rotation != objectupdate.Rotation || prim.ParentID != block.ParentID*/ ) { SimObject O = GetSimObjectFromUUID(prim.ID); if (O != null) { if (!isNewPrim) { Debug("PrimData changed for " + prim); O.PathFinding.RemoveCollisions(); } // the old OnNewPrim code will force the reindexing } else { //Debug("PrimData new for " + prim); O = GetSimObject(prim, simulator); return; } } if (!isNewPrim) { DeclareProperties(prim, prim.Properties, simulator); SendNewRegionEvent(SimEventType.DATA_UPDATE, "on-data-updated", prim); } //Objects_OnPrimitiveUpdate(simulator, prim, objectupdate0, simulator.Handle, 0); } else { //if (prim.RegionHandle == 0) // prim.RegionHandle = simulator.Handle; if (prim.ID != UUID.Zero) { SimObject O = GetSimObjectFromUUID(prim.ID); if (O != null && prim.Properties != null && prim.RegionHandle == simulator.Handle) { Objects_OnPrimitiveUpdateReal(simulator, prim, objectupdate0, simulator.Handle, 0); //O = GetSimObject(prim, simulator); } } } } }
// Local routine to create a mesh from prim parameters. // Collects parameters and calls PrimMesher to create all the faces of the prim. private LibreMetaverse.PrimMesher.PrimMesh GeneratePrimMesh(Primitive prim, DetailLevel lod, bool viewerMode) { Primitive.ConstructionData primData = prim.PrimData; int sides = 4; int hollowsides = 4; float profileBegin = primData.ProfileBegin; float profileEnd = primData.ProfileEnd; bool isSphere = false; if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.Circle) { switch (lod) { case OMVR.DetailLevel.Low: sides = 6; break; case OMVR.DetailLevel.Medium: sides = 12; break; default: sides = 24; break; } } else if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.EqualTriangle) { sides = 3; } else if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle) { // half circle, prim is a sphere isSphere = true; switch (lod) { case OMVR.DetailLevel.Low: sides = 6; break; case OMVR.DetailLevel.Medium: sides = 12; break; default: sides = 24; break; } profileBegin = 0.5f * profileBegin + 0.5f; profileEnd = 0.5f * profileEnd + 0.5f; } if (primData.ProfileHole == HoleType.Same) { hollowsides = sides; } else if (primData.ProfileHole == HoleType.Circle) { switch (lod) { case DetailLevel.Low: hollowsides = 6; break; case DetailLevel.Medium: hollowsides = 12; break; default: hollowsides = 24; break; } } else if (primData.ProfileHole == HoleType.Triangle) { hollowsides = 3; } PrimMesh newPrim = new PrimMesh(sides, profileBegin, profileEnd, primData.ProfileHollow, hollowsides) { viewerMode = viewerMode, sphereMode = isSphere, holeSizeX = primData.PathScaleX, holeSizeY = primData.PathScaleY, pathCutBegin = primData.PathBegin, pathCutEnd = primData.PathEnd, topShearX = primData.PathShearX, topShearY = primData.PathShearY, radius = primData.PathRadiusOffset, revolutions = primData.PathRevolutions, skew = primData.PathSkew }; switch (lod) { case DetailLevel.Low: newPrim.stepsPerRevolution = 6; break; case DetailLevel.Medium: newPrim.stepsPerRevolution = 12; break; default: newPrim.stepsPerRevolution = 24; break; } if (primData.PathCurve == PathCurve.Line || primData.PathCurve == PathCurve.Flexible) { newPrim.taperX = 1.0f - primData.PathScaleX; newPrim.taperY = 1.0f - primData.PathScaleY; newPrim.twistBegin = (int)(180 * primData.PathTwistBegin); newPrim.twistEnd = (int)(180 * primData.PathTwist); newPrim.ExtrudeLinear(); } else { newPrim.taperX = primData.PathTaperX; newPrim.taperY = primData.PathTaperY; newPrim.twistBegin = (int)(360 * primData.PathTwistBegin); newPrim.twistEnd = (int)(360 * primData.PathTwist); newPrim.ExtrudeCircular(); } return(newPrim); }
public static void WriteShape(XmlTextWriter writer, Primitive prim, Primitive.ObjectProperties props, Primitive.ConstructionData shp, ImportSettings options) { if (true /*shp != null*/) { writer.WriteStartElement("Shape"); WriteEnum(writer, "ProfileCurve", shp.ProfileCurve); writer.WriteStartElement("TextureEntry"); byte[] te; if (prim.Textures != null) { te = prim.Textures.GetBytes(); } else { te = Utils.EmptyBytes; } writer.WriteBase64(te, 0, te.Length); writer.WriteEndElement(); // TextureEntry writer.WriteStartElement("ExtraParams"); byte[] ep; if (prim.GetExtraParamsBytes() != null) { ep = prim.GetExtraParamsBytes(); } else { ep = Utils.EmptyBytes; } writer.WriteBase64(ep, 0, ep.Length); writer.WriteEndElement(); // ExtraParams writer.WriteElementString("PathBegin", Primitive.PackBeginCut(shp.PathBegin).ToString()); WriteEnum(writer, "PathCurve", shp.PathCurve); writer.WriteElementString("PathEnd", Primitive.PackEndCut(shp.PathEnd).ToString()); writer.WriteElementString("PathRadiusOffset", Primitive.PackPathTwist(shp.PathRadiusOffset).ToString()); writer.WriteElementString("PathRevolutions", Primitive.PackPathRevolutions(shp.PathRevolutions).ToString()); writer.WriteElementString("PathScaleX", Primitive.PackPathScale(shp.PathScaleX).ToString()); writer.WriteElementString("PathScaleY", Primitive.PackPathScale(shp.PathScaleY).ToString()); writer.WriteElementString("PathShearX", ((byte)Primitive.PackPathShear(shp.PathShearX)).ToString()); writer.WriteElementString("PathShearY", ((byte)Primitive.PackPathShear(shp.PathShearY)).ToString()); writer.WriteElementString("PathSkew", Primitive.PackPathTwist(shp.PathSkew).ToString()); writer.WriteElementString("PathTaperX", Primitive.PackPathTaper(shp.PathTaperX).ToString()); writer.WriteElementString("PathTaperY", Primitive.PackPathTaper(shp.PathTaperY).ToString()); writer.WriteElementString("PathTwist", Primitive.PackPathTwist(shp.PathTwist).ToString()); writer.WriteElementString("PathTwistBegin", Primitive.PackPathTwist(shp.PathTwistBegin).ToString()); writer.WriteElementString("ProfileBegin", Primitive.PackBeginCut(shp.ProfileBegin).ToString()); writer.WriteElementString("ProfileEnd", Primitive.PackEndCut(shp.ProfileEnd).ToString()); writer.WriteElementString("ProfileHollow", Primitive.PackProfileHollow(shp.ProfileHollow).ToString()); WriteEnum(writer, "PCode", shp.PCode); // this is Attachment in a way? WriteInt(writer, "State", shp.State); //WriteEnum(writer, "State", shp.AttachmentPoint); WriteFlags(writer, "ProfileShape", shp.ProfileCurve, options); WriteFlags(writer, "HollowShape", shp.ProfileHole, options); var Sculpt = prim.Sculpt; if (Sculpt != null) { WriteUUID(writer, "SculptTexture", Sculpt.SculptTexture, options); WriteEnum(writer, "SculptType", Sculpt.Type); writer.WriteStartElement("SculptData"); byte[] sd; if (prim.Sculpt != null) { sd = Sculpt.GetBytes(); } else { sd = Utils.EmptyBytes; } writer.WriteBase64(sd, 0, sd.Length); writer.WriteEndElement(); // SculptData } Primitive.FlexibleData Flexi = prim.Flexible; if (Flexi != null) { WriteInt(writer, "FlexiSoftness", Flexi.Softness); WriteFloat(writer, "FlexiTension", Flexi.Tension); WriteFloat(writer, "FlexiDrag", Flexi.Drag); WriteFloat(writer, "FlexiGravity", Flexi.Gravity); WriteFloat(writer, "FlexiWind", Flexi.Wind); WriteFloat(writer, "FlexiForceX", Flexi.Force.X); WriteFloat(writer, "FlexiForceY", Flexi.Force.Y); WriteFloat(writer, "FlexiForceZ", Flexi.Force.Z); } Primitive.LightData Light = prim.Light; if (Light != null) { WriteFloat(writer, "LightColorR", Light.Color.R); WriteFloat(writer, "LightColorG", Light.Color.G); WriteFloat(writer, "LightColorB", Light.Color.B); WriteFloat(writer, "LightColorA", Light.Color.A); WriteFloat(writer, "LightRadius", Light.Radius); WriteFloat(writer, "LightCutoff", Light.Cutoff); WriteFloat(writer, "LightFalloff", Light.Falloff); WriteFloat(writer, "LightIntensity", Light.Intensity); } WriteValue(writer, "FlexiEntry", (Flexi != null).ToString().ToLower()); WriteValue(writer, "LightEntry", (Light != null).ToString().ToLower()); WriteValue(writer, "SculptEntry", (Sculpt != null).ToString().ToLower()); //todo if (shp.Media != null) WES(writer,"Media", shp.Media.ToXml()); writer.WriteEndElement(); // Shape } }
// Processes object update packets (Avatars and Objects entering drawing distance) private Packet ProcessObjectUpdate(Packet packet, IPEndPoint endpoint) { ObjectUpdatePacket update = (ObjectUpdatePacket)packet; for (int b = 0; b < update.ObjectData.Length; b++) { ObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[b]; ObjectMovementUpdate objectupdate = new ObjectMovementUpdate(); NameValue[] nameValues; string firstname = ""; string lastname = ""; PCode pcode = (PCode)block.PCode; #region NameValue parsing string nameValue = Utils.BytesToString(block.NameValue); if (nameValue.Length > 0) { string[] lines = nameValue.Split('\n'); nameValues = new NameValue[lines.Length]; for (int i = 0; i < lines.Length; i++) { if (!String.IsNullOrEmpty(lines[i])) { NameValue nv = new NameValue(lines[i]); if (nv.Name == "FirstName") { firstname = nv.Value.ToString(); } if (nv.Name == "LastName") { lastname = nv.Value.ToString(); } nameValues[i] = nv; } } } else { nameValues = new NameValue[0]; } #endregion NameValue parsing #region Decode Object (primitive) parameters Primitive.ConstructionData data = new Primitive.ConstructionData(); data.State = block.State; data.Material = (Material)block.Material; data.PathCurve = (PathCurve)block.PathCurve; data.profileCurve = block.ProfileCurve; data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin); data.PathEnd = Primitive.UnpackEndCut(block.PathEnd); data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX); data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY); data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX); data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY); data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist); data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin); data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset); data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX); data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY); data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions); data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew); data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin); data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd); data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); data.PCode = pcode; #endregion #region Decode Additional packed parameters in ObjectData int pos = 0; switch (block.ObjectData.Length) { case 76: // Collision normal for avatar objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos); pos += 16; goto case 60; case 60: // Position objectupdate.Position = new Vector3(block.ObjectData, pos); pos += 12; // Velocity objectupdate.Velocity = new Vector3(block.ObjectData, pos); pos += 12; // Acceleration objectupdate.Acceleration = new Vector3(block.ObjectData, pos); pos += 12; // Rotation (theta) objectupdate.Rotation = new Quaternion(block.ObjectData, pos, true); pos += 12; // Angular velocity (omega) objectupdate.AngularVelocity = new Vector3(block.ObjectData, pos); pos += 12; break; case 48: // Collision normal for avatar objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos); pos += 16; goto case 32; case 32: // The data is an array of unsigned shorts // Position objectupdate.Position = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -0.5f * 256.0f, 1.5f * 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -0.5f * 256.0f, 1.5f * 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 3.0f * 256.0f)); pos += 6; // Velocity objectupdate.Velocity = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; // Acceleration objectupdate.Acceleration = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; // Rotation (theta) objectupdate.Rotation = new Quaternion( Utils.UInt16ToFloat(block.ObjectData, pos, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -1.0f, 1.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 6, -1.0f, 1.0f)); pos += 8; // Angular velocity (omega) objectupdate.AngularVelocity = new Vector3( Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f), Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f)); pos += 6; break; case 16: // The data is an array of single bytes (8-bit numbers) // Position objectupdate.Position = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Velocity objectupdate.Velocity = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Accleration objectupdate.Acceleration = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; // Rotation objectupdate.Rotation = new Quaternion( Utils.ByteToFloat(block.ObjectData, pos, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f), Utils.ByteToFloat(block.ObjectData, pos + 3, -1.0f, 1.0f)); pos += 4; // Angular Velocity objectupdate.AngularVelocity = new Vector3( Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f), Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f)); pos += 3; break; default: SayToUser("ERROR: Got an ObjectUpdate block with ObjectUpdate field length of " + block.ObjectData.Length); continue; } #endregion // Determine the object type and create the appropriate class switch (pcode) { #region Prim and Foliage case PCode.Grass: case PCode.Tree: case PCode.NewTree: case PCode.Prim: break; #endregion Prim and Foliage #region Avatar case PCode.Avatar: if (block.FullID == this.frame.AgentID) { mylocalid = block.ID; StatusSetLocalID(mylocalid.ToString()); } #region Create an Avatar from the decoded data Avatar avatar = new Avatar(); if (Avatars.ContainsKey(block.ID)) { avatar = Avatars[block.ID]; } objectupdate.Avatar = true; // Textures objectupdate.Textures = new Primitive.TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); uint oldSeatID = avatar.ParentID; avatar.ID = block.FullID; avatar.LocalID = block.ID; avatar.CollisionPlane = objectupdate.CollisionPlane; avatar.Position = objectupdate.Position; avatar.Velocity = objectupdate.Velocity; avatar.Acceleration = objectupdate.Acceleration; avatar.Rotation = objectupdate.Rotation; avatar.AngularVelocity = objectupdate.AngularVelocity; avatar.NameValues = nameValues; avatar.PrimData = data; if (block.Data.Length > 0) { SayToUser("ERROR: Unexpected Data field for an avatar update, length " + block.Data.Length); } avatar.ParentID = block.ParentID; avatar.RegionHandle = update.RegionData.RegionHandle; // Textures avatar.Textures = objectupdate.Textures; // Save the avatar lock (Avatars) Avatars[block.ID] = avatar; // Fill up the translation dictionaries lock (AvatarIDtoUUID) AvatarIDtoUUID[block.ID] = block.FullID; lock (AvatarUUIDtoID) AvatarUUIDtoID[block.FullID] = block.ID; lock (AvatarUUIDToName) AvatarUUIDToName[block.FullID] = firstname + " " + lastname; lock (AvatarNameToUUID) AvatarNameToUUID[firstname + " " + lastname] = block.FullID; #endregion Create an Avatar from the decoded data break; #endregion Avatar case PCode.ParticleSystem: // ConsoleWriteLine("ERROR: Got a particle system update."); // // TODO: Create a callback for particle updates break; default: SayToUser("ERROR: Got an ObjectUpdate block with an unrecognized PCode " + pcode.ToString()); break; } } return(packet); }