コード例 #1
0
        /// <summary>
        /// Message handler for <see cref="CreateMessage"/>
        /// </summary>
        /// <param name="msg">The incoming message.</param>
        /// <param name="packet">The buffer containing the message.</param>
        /// <param name="reader">The reader from which the message came.</param>
        /// <returns>An error code on failure.</returns>
        /// <remarks>
        /// Creates either a persistent or transient object depending on the incoming
        /// message ObjectID. An ID of zero signifies a transient object.
        /// Solid or wire shapes are assigned according to the message flags.
        /// </remarks>
        protected virtual Error HandleMessage(CreateMessage msg, PacketBuffer packet, BinaryReader reader)
        {
            GameObject obj = null;

            if (msg.ObjectID == 0)
            {
                // Transient object.
                obj = CreateTransient();
            }
            else
            {
                obj = CreateObject(msg.ObjectID);
                if (!obj)
                {
                    // Object already exists.
                    return(new Error(ErrorCode.DuplicateShape, msg.ObjectID));
                }
            }

            ShapeComponent shapeComp = obj.GetComponent <ShapeComponent>();

            shapeComp.Category    = msg.Category;
            shapeComp.ObjectFlags = msg.Flags;
            shapeComp.Colour      = ShapeComponent.ConvertColour(msg.Attributes.Colour);

            obj.transform.SetParent(_root.transform, false);
            DecodeTransform(msg.Attributes, obj.transform);

            InitialiseVisual(shapeComp, ShapeComponent.ConvertColour(msg.Attributes.Colour));

            return(PostHandleMessage(obj, msg, packet, reader));
        }
コード例 #2
0
        /// <summary>
        /// Handles <see cref="MeshRedefineMessage"/>
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        /// <remarks>
        /// The associated mesh is invalidated until another <see cref="MeshFinaliseMessage"/> arrives.
        /// </remarks>
        protected Error RedefineMesh(PacketBuffer packet, BinaryReader reader)
        {
            MeshRedefineMessage msg = new MeshRedefineMessage();

            if (!msg.Read(reader))
            {
                return(new Error(ErrorCode.MalformedMessage, MeshRedefineMessage.MessageID));
            }

            MeshDetails meshDetails;

            if (!_meshes.TryGetValue(msg.MeshID, out meshDetails))
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.MeshID));
            }

            meshDetails.Finalised = false;
            if (msg.VertexCount != meshDetails.VertexCount)
            {
                meshDetails.VertexCount = (int)msg.VertexCount;
            }
            if (msg.IndexCount != 0)
            {
                meshDetails.IndexCount = (int)msg.IndexCount;
            }

            meshDetails.ID            = msg.MeshID;
            meshDetails.LocalPosition = new Vector3(msg.Attributes.X, msg.Attributes.Y, msg.Attributes.Z);
            meshDetails.LocalRotation = new Quaternion(msg.Attributes.RotationX, msg.Attributes.RotationY, msg.Attributes.RotationZ, msg.Attributes.RotationW);
            meshDetails.LocalScale    = new Vector3(msg.Attributes.ScaleX, msg.Attributes.ScaleY, msg.Attributes.ScaleZ);
            meshDetails.Tint          = ShapeComponent.ConvertColour(msg.Attributes.Colour);

            return(new Error());
        }
コード例 #3
0
        /// <summary>
        /// Message handler for <see cref="UpdateMessage"/>
        /// </summary>
        /// <param name="msg">The incoming message.</param>
        /// <param name="packet">The buffer containing the message.</param>
        /// <param name="reader">The reader from which the message came.</param>
        /// <returns>An error code on failure.</returns>
        /// <remarks>
        /// Decodes the message transform and colour, updating the existing shape
        /// matching the message ObjectID. Only relevant for persistent shapes.
        /// </remarks>
        protected virtual Error HandleMessage(UpdateMessage msg, PacketBuffer packet, BinaryReader reader)
        {
            GameObject obj = FindObject(msg.ObjectID);

            if (obj == null)
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.ObjectID));
            }

            ushort flags = msg.Flags;

            DecodeTransform(msg.Attributes, obj.transform, flags);

            if ((flags & (ushort)UpdateFlag.UpdateMode) == 0 || (flags & (ushort)UpdateFlag.Colour) != 0)
            {
                ShapeComponent shapeComp = obj.GetComponent <ShapeComponent>();
                if (shapeComp != null)
                {
                    shapeComp.Colour = ShapeComponent.ConvertColour(msg.Attributes.Colour);
                }

                SetColour(obj, ShapeComponent.ConvertColour(msg.Attributes.Colour));
            }

            return(new Error());
        }
コード例 #4
0
        /// <summary>
        /// Called at end of <see cref="HandleMessage(CreateMessage, PacketBuffer, BinaryReader)"/>, only on success.
        /// </summary>
        /// <param name="obj">The newly created message.</param>
        /// <param name="msg">The incoming message.</param>
        /// <param name="packet">The buffer containing the message.</param>
        /// <param name="reader">The reader from which the message came.</param>
        /// <returns>An error code on failure.</returns>
        protected virtual Error PostHandleMessage(GameObject obj, CreateMessage msg, PacketBuffer packet, BinaryReader reader)
        {
            ShapeComponent shape = obj.GetComponent <ShapeComponent>();

            if (shape != null && !CategoryCheck(shape.Category))
            {
                obj.SetActive(false);
            }
            return(new Error());
        }
コード例 #5
0
        /// <summary>
        /// A helper functio to configure the TES <paramref name="shape"/> to match the Unity object <paramref name="shapeComponent"/>.
        /// </summary>
        /// <param name="shape">The shape object to configure to match the Unity representation.</param>
        /// <param name="shapeComponent">The Unity shape representation.</param>
        protected void ConfigureShape(Shapes.Shape shape, ShapeComponent shapeComponent)
        {
            ObjectAttributes attr = new ObjectAttributes();

            shape.ID       = shapeComponent.ObjectID;
            shape.Category = shapeComponent.Category;
            shape.Flags    = shapeComponent.ObjectFlags;
            EncodeAttributes(ref attr, shapeComponent.gameObject, shapeComponent);
            shape.SetAttributes(attr);
        }
コード例 #6
0
        /// <summary>
        /// Serialise messages to generate <paramref name="mesh"/>.
        /// </summary>
        /// <param name="mesh">The mesh of interest.</param>
        /// <param name="packet">Packet buffer to compose messages in</param>
        /// <param name="writer">Writer to export completed message packets to.</param>
        /// <returns></returns>
        /// <remarks>
        /// Writes:
        /// <list type="bullet">
        /// <item><see cref="MeshCreateMessage"/></item>
        /// <item><see cref="MeshComponentMessage"/> for each component type from
        /// <see cref="MeshMessageType"/></item>
        /// <item><see cref="MeshFinaliseMessage"/> only when <paramref name="mesh"/> is already
        /// finalised.</item>
        /// </list>
        /// </remarks>
        protected Error Serialise(MeshDetails mesh, PacketBuffer packet, BinaryWriter writer)
        {
            // First write a create message.
            MeshCreateMessage msg = new MeshCreateMessage();

            packet.Reset((ushort)RoutingID, (ushort)MeshCreateMessage.MessageID);

            msg.MeshID      = mesh.ID;
            msg.VertexCount = (uint)mesh.Builder.VertexCount;
            msg.IndexCount  = (uint)(mesh.Builder.ExplicitIndices ? mesh.Builder.IndexCount : 0);
            msg.DrawType    = mesh.DrawType;

            msg.Attributes.X = mesh.LocalPosition.x;
            msg.Attributes.Y = mesh.LocalPosition.y;
            msg.Attributes.Z = mesh.LocalPosition.z;

            msg.Attributes.RotationX = mesh.LocalRotation.x;
            msg.Attributes.RotationY = mesh.LocalRotation.y;
            msg.Attributes.RotationZ = mesh.LocalRotation.z;
            msg.Attributes.RotationW = mesh.LocalRotation.w;

            msg.Attributes.ScaleX = mesh.LocalScale.x;
            msg.Attributes.ScaleY = mesh.LocalScale.y;
            msg.Attributes.ScaleZ = mesh.LocalScale.z;

            msg.Attributes.Colour = ShapeComponent.ConvertColour(mesh.Tint);

            msg.Write(packet);
            if (!packet.FinalisePacket())
            {
                return(new Error(ErrorCode.SerialisationFailure));
            }
            packet.ExportTo(writer);

            // Now use the MeshResource methods to complete serialisation.
            MeshSerialiser   serialiser = new MeshSerialiser(mesh);
            TransferProgress prog       = new TransferProgress();

            prog.Reset();
            while (!prog.Complete)
            {
                serialiser.Transfer(packet, 0, ref prog);
                if (!packet.FinalisePacket())
                {
                    return(new Error(ErrorCode.SerialisationFailure));
                }
                packet.ExportTo(writer);
            }

            return(new Error());
        }
コード例 #7
0
        /// <summary>
        /// Handles <see cref="MeshCreateMessage"/>
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        /// <remarks>
        /// Emits <see cref="OnMeshAdded"/>.
        /// </remarks>
        protected Error CreateMesh(PacketBuffer packet, BinaryReader reader)
        {
            MeshCreateMessage msg = new MeshCreateMessage();

            if (!msg.Read(reader))
            {
                return(new Error(ErrorCode.MalformedMessage, MeshCreateMessage.MessageID));
            }

            if (_meshes.ContainsKey(msg.MeshID))
            {
                return(new Error(ErrorCode.DuplicateShape, msg.MeshID));
            }

            MeshDetails meshDetails = new MeshDetails();

            meshDetails.VertexCount = (int)msg.VertexCount;
            meshDetails.IndexCount  = (int)msg.IndexCount;
            meshDetails.DrawType    = msg.DrawType;
            switch (msg.DrawType)
            {
            case (byte)MeshDrawType.Points:
            // No break.
            case (byte)MeshDrawType.Voxels:
                meshDetails.Builder.Topology = MeshTopology.Points;
                break;

            case (byte)MeshDrawType.Lines:
                meshDetails.Builder.Topology = MeshTopology.Lines;
                break;

            case (byte)MeshDrawType.Triangles:
                meshDetails.Builder.Topology = MeshTopology.Triangles;
                break;

            default:
                return(new Error(ErrorCode.UnsupportedFeature, msg.DrawType));
            }

            meshDetails.ID            = msg.MeshID;
            meshDetails.LocalPosition = new Vector3(msg.Attributes.X, msg.Attributes.Y, msg.Attributes.Z);
            meshDetails.LocalRotation = new Quaternion(msg.Attributes.RotationX, msg.Attributes.RotationY, msg.Attributes.RotationZ, msg.Attributes.RotationW);
            meshDetails.LocalScale    = new Vector3(msg.Attributes.ScaleX, msg.Attributes.ScaleY, msg.Attributes.ScaleZ);
            meshDetails.Tint          = ShapeComponent.ConvertColour(msg.Attributes.Colour);
            meshDetails.Finalised     = false;
            _meshes.Add(meshDetails.ID, meshDetails);

            NotifyMeshAdded(meshDetails);

            return(new Error());
        }
コード例 #8
0
        /// <summary>
        /// Instantiates a persistent object from the <see cref="ShapeCache"/>.
        /// The new object is assigned the given <paramref name="id"/>
        /// </summary>
        /// <param name="id">The ID of the new object. Must non be zero (for persistent objects).</param>
        /// <returns>The instantiated object or null on failure.</returns>
        protected virtual GameObject CreateObject(uint id)
        {
            GameObject obj = CreateObject();

            obj.name = string.Format("{0}{1:D3}", Name, id);
            ShapeComponent shape = obj.GetComponent <ShapeComponent>();

            shape.ObjectID = id;
            if (_shapeCache.Add(id, obj))
            {
                return(obj);
            }
            // Creation failed.
            GameObject.Destroy(obj);
            return(null);
        }
コード例 #9
0
        /// <summary>
        /// Handles <see cref="MeshComponentMessage"/> of type <see cref="MeshMessageType.VertexColour"/>.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected Error AddVertexColours(PacketBuffer packet, BinaryReader reader)
        {
            MeshComponentMessage msg = new MeshComponentMessage();

            if (!msg.Read(reader))
            {
                return(new Error(ErrorCode.MalformedMessage, (ushort)MeshMessageType.VertexColour));
            }

            MeshDetails meshDetails;

            if (!_meshes.TryGetValue(msg.MeshID, out meshDetails))
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.MeshID));
            }

            if (msg.Count == 0)
            {
                return(new Error());
            }

            int voffset = (int)msg.Offset;
            // Bounds check.
            int vertexCount = (int)meshDetails.VertexCount;

            if (voffset >= vertexCount || voffset + msg.Count > vertexCount)
            {
                return(new Error(ErrorCode.IndexingOutOfRange, (ushort)MeshMessageType.VertexColour));
            }

            // Check for settings initial bounds.
            bool ok = true;
            uint colour;

            for (int vInd = 0; ok && vInd < msg.Count; ++vInd)
            {
                colour = reader.ReadUInt32();
                meshDetails.Builder.UpdateColour(vInd + voffset, ShapeComponent.ConvertColour(colour));
            }

            if (!ok)
            {
                return(new Error(ErrorCode.MalformedMessage, (ushort)MeshMessageType.VertexColour));
            }

            return(new Error());
        }
コード例 #10
0
        /// <summary>
        /// Invoked when an object category changes active state.
        /// </summary>
        /// <param name="categoryId">The category changing state.</param>
        /// <param name="active">The new active state.</param>
        /// <remarks>
        /// Handlers should only ever visualise objects in active categories.
        /// </remarks>
        public override void OnCategoryChange(ushort categoryId, bool active)
        {
            foreach (GameObject obj in _transientCache.Objects)
            {
                ShapeComponent shape = obj.GetComponent <ShapeComponent>();
                if (shape != null && shape.Category == categoryId)
                {
                    obj.SetActive(active);
                }
            }

            foreach (GameObject obj in _shapeCache.Objects)
            {
                ShapeComponent shape = obj.GetComponent <ShapeComponent>();
                if (shape != null && shape.Category == categoryId)
                {
                    obj.SetActive(active);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Lookup a material for the given <paramref name="shape"/> created by this handler.
        /// </summary>
        /// <param name="shape">The shape to lookup a material for.</param>
        /// <returns>The material for that shape.</returns>
        /// <remarks>
        /// Respects various <see cref="ObjectFlag"/> values.
        /// </remarks>
        public virtual Material LookupMaterialFor(ShapeComponent shape)
        {
            if (shape.Wireframe)
            {
                // Note: Wireframe triangles is not for rendering line shapes, but outlining triangles.
                // Therefore, not what we want here.
                return(Materials[MaterialLibrary.VertexColourUnlit]);
            }

            if (shape.Transparent)
            {
                return(Materials[MaterialLibrary.VertexColourTransparent]);
            }

            if (shape.TwoSided)
            {
                return(Materials[MaterialLibrary.VertexColourUnlitTwoSided]);
            }

            return(Materials[MaterialLibrary.VertexColourUnlit]);
        }
コード例 #12
0
        /// <summary>
        /// Sets the render meshes for <paramref name="obj"/> using <paramref name="sharedMeshes"/>.
        /// </summary>
        /// <param name="obj">The object to initialise visuals for.</param>
        /// <param name="sharedMeshes">The meshes to render with.</param>
        /// <param name="colour">Primary rendering colour.</param>
        /// <remarks>
        /// This function sets <paramref name="sharedMeshes"/> as a set of shared mesh resources
        /// to render <paramref name="obj"/> with. When there is one element in
        /// <paramref name="sharedMeshes"/>, the mesh and material are set on the
        /// <c>MeshFilter</c> and <c>MeshRenderer</c> belonging to <paramref name="obj"/> itself.
        /// When multiple items are given, the children of <paramref name="obj"/> are used instead.
        /// This means the number of children must match the number of elements in
        /// <paramref name="sharedMeshes"/>.
        ///
        /// The materials used are attained via <see cref="LookupMaterialFor(ShapeComponent)"/>
        /// where the <see cref="ShapeComponent"/> belongs to <paramref name="obj"/>.
        /// </remarks>
        protected virtual void InitialiseMesh(ShapeComponent obj, Mesh[] sharedMeshes, Color colour)
        {
            MeshFilter     filter = obj.GetComponent <MeshFilter>();
            MeshRenderer   render = obj.GetComponent <MeshRenderer>();
            ShapeComponent shape  = obj.GetComponent <ShapeComponent>();

            if (sharedMeshes.Length == 1)
            {
                // Single mesh. Set on this object.
                if (filter != null)
                {
                    filter.sharedMesh = sharedMeshes[0];
                    if (render != null)
                    {
                        int componentCount = (filter.sharedMesh != null) ? filter.sharedMesh.subMeshCount : 0;
                        SetMaterial(LookupMaterialFor(shape), render, componentCount, colour);
                    }
                }
            }
            else
            {
                // Multiple meshes. Set on children.
                Transform child;
                for (int i = 0; i < sharedMeshes.Length; ++i)
                {
                    child = obj.transform.GetChild(i);
                    if ((filter = child.GetComponent <MeshFilter>()) != null)
                    {
                        filter.sharedMesh = sharedMeshes[i];
                    }

                    if ((render = child.GetComponent <MeshRenderer>()))
                    {
                        SetMaterial(LookupMaterialFor(shape), render, sharedMeshes[i].subMeshCount, colour);
                    }
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Called to extract the current object attributes from an existing object.
        /// </summary>
        /// <param name="attr">Modified to reflect the current state of <paramref name="obj"/></param>
        /// <param name="obj">The object to encode attributes for.</param>
        /// <param name="comp">The <see cref="ShapeComponent"/> of <paramref name="obj"/></param>
        /// <remarks>
        /// This extracts colour and performs the inverse operation of <see cref="DecodeTransform"/>
        /// This method must be overridden whenever <see cref="DecodeTransform"/> is overridden.
        /// </remarks>
        protected virtual void EncodeAttributes(ref ObjectAttributes attr, GameObject obj, ShapeComponent comp)
        {
            Transform transform = obj.transform;

            attr.X         = transform.localPosition.x;
            attr.Y         = transform.localPosition.y;
            attr.Z         = transform.localPosition.z;
            attr.RotationX = transform.localRotation.x;
            attr.RotationY = transform.localRotation.y;
            attr.RotationZ = transform.localRotation.z;
            attr.RotationW = transform.localRotation.w;
            attr.ScaleX    = transform.localScale.x;
            attr.ScaleY    = transform.localScale.y;
            attr.ScaleZ    = transform.localScale.z;
            if (comp != null)
            {
                attr.Colour = ShapeComponent.ConvertColour(comp.Colour);
            }
            else
            {
                attr.Colour = 0xffffffu;
            }
        }
コード例 #14
0
 protected override Shapes.Shape CreateSerialisationShape(Handlers.ShapeComponent shapeComponent)
 {
     Shapes.Shape shape = new Pyramid();
     ConfigureShape(shape, shapeComponent);
     return(shape);
 }
コード例 #15
0
 /// <summary>
 /// A convenient overload accepting a single mesh argument.
 /// </summary>
 /// <param name="obj">The object to initialise visuals for.</param>
 /// <param name="sharedMesh">The mesh to render with.</param>
 /// <param name="colour">Primary rendering colour.</param>
 /// <remarks>
 /// Maps to the overload: <see cref="InitialiseMesh(ShapeComponent, Mesh[], Color)"/>.
 /// </remarks>
 protected virtual void InitialiseMesh(ShapeComponent obj, Mesh sharedMesh, Color colour)
 {
     InitialiseMesh(obj, new Mesh[] { sharedMesh }, colour);
 }
コード例 #16
0
        /// <summary>
        /// Initialise the visual components (e.g., meshes) for <paramref name="obj"/>.
        /// </summary>
        /// <param name="obj">The object to initialise visuals for.</param>
        /// <param name="colour">Primary rendering colour.</param>
        /// <remarks>
        /// The default implementation resolves a single mesh using <see cref="SolidMesh"/>
        /// or <see cref="WireframeMesh"/> (depending on <see cref="ShapeComponent.Wireframe"/>)
        /// and invokes <see cref="InitialiseMesh(ShapeComponent, Mesh, Color)"/>.
        /// </remarks>
        protected virtual void InitialiseVisual(ShapeComponent obj, Color colour)
        {
            Mesh sharedMesh = (!obj.Wireframe) ? SolidMesh : WireframeMesh;

            InitialiseMesh(obj, sharedMesh, colour);
        }
コード例 #17
0
 /// <summary>
 /// Create a dummy shape object used to generate serialisation messages.
 /// </summary>
 /// <param name="shapeComponent">The component to create a shape for.</param>
 /// <returns>A shape instance suitable for configuring to generate serialisation messages.</returns>
 /// <remarks>
 /// Base classes should implement this method to return an instance of the appropriate
 /// <see cref="Shapes.Shape"/> derivation. For example, the <see cref="Shape3D.SphereHandler"/>
 /// should return a <see cref="Shapes.Sphere"/> object. See
 /// <see cref="SerialiseObjects(BinaryWriter, IEnumerator&lt;GameObject&gt;, ref uint)"/> for further
 /// details.
 /// </remarks>
 protected abstract Shapes.Shape CreateSerialisationShape(ShapeComponent shapeComponent);
コード例 #18
0
 /// <summary>
 /// Called after serialising the creation message for an object. This allows follow up
 /// data messages to be serialised.
 /// </summary>
 /// <param name="packet"></param>
 /// <param name="writer"></param>
 /// <param name="shape"></param>
 /// <returns></returns>
 protected virtual Error PostSerialiseCreateObject(PacketBuffer packet, BinaryWriter writer, ShapeComponent shape)
 {
     return(new Error());
 }