Esempio n. 1
0
File: gxtLine.cs Progetto: Loko/GXT
 public gxtAABB GetAABB(Vector2 position, float rotation, Vector2 scale)
 {
     Vector2 c = (Start + End) * 0.5f;
     float rX = gxtMath.Abs((End.X - c.X) * scale.X);
     float rY = gxtMath.Abs((End.Y - c.Y) * scale.Y);
     gxtAABB localAABB = new gxtAABB(c, new Vector2(rX, rY));
     return gxtAABB.Update(position, rotation, localAABB);
 }
Esempio n. 2
0
 public gxtDynamicIndexedPrimitive(Vector2[] verts, PrimitiveType primitiveType = PrimitiveType.TriangleList)
 {
     gxtDebug.Assert(gxtRoot.SingletonIsInitialized);
     this.primitiveType = primitiveType;
     int indicesArraySize = CalcIndicesArraySize(verts.Length, primitiveType);
     this.primitiveCount = CalcPrimitiveCount(indicesArraySize, primitiveType);
     SetupVertices(verts);
     SetupIndices(indicesArraySize, primitiveType);
     localAABB = gxtGeometry.ComputeAABB(verts);
 }
Esempio n. 3
0
        public gxtDynamicIndexedPrimitive(Vector2[] verts, PrimitiveType primitiveType, gxtIMaterial material, Texture2D texture, Vector2[] textureCoordinates)
        {
            gxtDebug.Assert(gxtRoot.SingletonIsInitialized);
            this.primitiveType = primitiveType;
            int indicesArraySize = CalcIndicesArraySize(verts.Length, primitiveType);

            this.material = material;
            this.texture = texture;
            // set up vertices
            SetupVertices(verts, textureCoordinates);
            SetupIndices(indicesArraySize, primitiveType);
            localAABB = gxtGeometry.ComputeAABB(verts);
        }
Esempio n. 4
0
File: gxtRay.cs Progetto: Loko/GXT
        /// <summary>
        /// A simple boolean ray-aabb intersection test with options 
        /// for max values of t and inside/outside checks
        /// </summary>
        /// <param name="aabb">AABB</param>
        /// <param name="tmax">Max Distance</param>
        /// <param name="insideIsCollision">If the ray origin inside the AABB still counts as a collision</param>
        /// <returns>If intersecting</returns>
        public bool IntersectsAABB(gxtAABB aabb, float tmax = float.MaxValue, bool insideIsCollision = false)
        {
            gxtDebug.Assert(tmax >= 0.0f);

            // special case, confirms a collision if the origin is inside the AABB
            // only set insideIsCollision to true if the AABB is for a more complex
            // narrowphase shape (e.g. a polygon)
            if (insideIsCollision)
                if (aabb.Contains(origin))
                    return true;

            Vector2 absDirection = new Vector2(gxtMath.Abs(direction.X), gxtMath.Abs(direction.Y));

            Vector2 aabbMin = aabb.Min;
            Vector2 aabbMax = aabb.Max;

            float tmin = float.MinValue;
            //float tmax = float.MaxValue;

            if (absDirection.X < float.Epsilon)
            {
                // then we know it is parallel
                if (origin.X < aabbMin.X || origin.X > aabbMax.X)
                {
                    return false;
                }
            }
            else
            {
                float oneOverDX = 1.0f / direction.X;
                float t1X = (aabbMin.X - origin.X) * oneOverDX;
                float t2X = (aabbMax.X - origin.X) * oneOverDX;

                if (t1X > t2X)
                {
                    float holderTX = t1X;
                    t1X = t2X;
                    t2X = holderTX;
                }
                if (t1X > tmin)
                {
                    tmin = t1X;
                }

                tmax = gxtMath.Min(tmax, t2X);

                if (tmin > tmax)
                    return false;
            }
            if (absDirection.Y < float.Epsilon)
            {
                // then we know it is parallel
                if (origin.Y < aabbMin.Y || origin.Y > aabbMax.Y)
                {
                    return false;
                }
            }
            else
            {
                float oneOverDY = 1.0f / direction.Y;
                float t1Y = (aabbMin.Y - origin.Y) * oneOverDY;
                float t2Y = (aabbMax.Y - origin.Y) * oneOverDY;

                if (t1Y > t2Y)
                {
                    float holderTY = t1Y;
                    t1Y = t2Y;
                    t2Y = holderTY;
                }
                if (t1Y > tmin)
                {
                    tmin = t1Y;
                }

                tmax = gxtMath.Min(tmax, t2Y);

                if (tmin > tmax)
                    return false;
            }

            if (tmin < 0.0f || tmax < tmin)
                return false;

            return true;
        }
Esempio n. 5
0
        public void SetVertices(Vector2[] verts, Vector2[] textureCoordinates, bool setDefaultIndices = true)
        {
            gxtDebug.Assert(verts != null && verts.Length >= 3);
            gxtDebug.Assert(indices != null && indices.Length >= 3);
            gxtDebug.Assert(textureCoordinates != null && textureCoordinates.Length >= 3);
            gxtDebug.Assert(verts.Length == textureCoordinates.Length);

            vertices = new VertexPositionColorTexture[verts.Length];
            if (vertexBuffer == null)
                vertexBuffer = new DynamicVertexBuffer(gxtRoot.Singleton.Graphics, typeof(VertexPositionColorTexture), verts.Length, BufferUsage.WriteOnly);

            if (material == null)
            {
                for (int i = 0; i < verts.Length; ++i)
                {
                    vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), gxtMaterial.DEFAULT_COLOR_OVERLAY, textureCoordinates[i]);
                }
            }
            else
            {
                for (int i = 0; i < verts.Length; ++i)
                {
                    vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), material.ColorOverlay, textureCoordinates[i]);
                }
            }
            vertexBuffer.SetData<VertexPositionColorTexture>(vertices);
            localAABB = gxtGeometry.ComputeAABB(verts);

            if (setDefaultIndices)
                SetDefaultIndices(3 + ((verts.Length - 3) * 3));
        }
Esempio n. 6
0
        public void SetVertices(Vector2[] verts, bool setDefaultIndices = true)
        {
            gxtDebug.Assert(verts != null && verts.Length >= 3, "Vertices in a triangle mesh cannot be null or have a size less than 3!");

            vertices = new VertexPositionColorTexture[verts.Length];
            if (vertexBuffer == null)
                vertexBuffer = new DynamicVertexBuffer(gxtRoot.Singleton.Graphics, typeof(VertexPositionColorTexture), verts.Length, BufferUsage.WriteOnly);

            if (material == null)
            {
                for (int i = 0; i < verts.Length; ++i)
                {
                    vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), gxtMaterial.DEFAULT_COLOR_OVERLAY, Vector2.Zero);
                }
            }
            else
            {
                for (int i = 0; i < verts.Length; ++i)
                {
                    vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), gxtMaterial.DEFAULT_COLOR_OVERLAY, Vector2.Zero);
                }
            }
            vertexBuffer.SetData<VertexPositionColorTexture>(vertices);
            localAABB = gxtGeometry.ComputeAABB(verts);

            if (setDefaultIndices)
                SetDefaultIndices(3 + ((verts.Length - 3) * 3));
        }
Esempio n. 7
0
        public void SetupMesh(Vector2[] verts, int[] indices, Vector2[] textureCoordinates)
        {
            gxtDebug.Assert(verts != null && verts.Length >= 3, "Vertices array is null or less than 3 vertices");
            gxtDebug.Assert(indices != null && indices.Length >= 3, "Indices array is null or less than 3 indices");
            gxtDebug.Assert(textureCoordinates != null && textureCoordinates.Length >= 3, "Texture Coordinates array is null or less than 3 UV coordinates");
            gxtDebug.Assert(verts.Length == textureCoordinates.Length, "The vertices array and texture coordinates array have a size mismatch!");

            // set up verts
            vertices = new VertexPositionColorTexture[verts.Length];
            if (vertexBuffer == null)
                vertexBuffer = new DynamicVertexBuffer(gxtRoot.Singleton.Graphics, typeof(VertexPositionColorTexture), verts.Length, BufferUsage.WriteOnly);

            Color overlay = (material != null) ? material.ColorOverlay : gxtMaterial.DEFAULT_COLOR_OVERLAY;
            for (int i = 0; i < verts.Length; ++i)
            {
                vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), overlay, textureCoordinates[i]);
            }
            vertexBuffer.SetData<VertexPositionColorTexture>(vertices);
            localAABB = gxtGeometry.ComputeAABB(verts);

            // set up indices
            // deep copy necessary?
            for (int i = 0; i < indices.Length; ++i)
            {
                this.indices[i] = indices[i];
            }
            if (indexBuffer == null)
                indexBuffer = new DynamicIndexBuffer(gxtRoot.Singleton.Graphics, typeof(int), indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData<int>(indices);
            this.primitiveCount = indices.Length / 3;
        }
Esempio n. 8
0
        /// <summary>
        /// Gets the merged world space AABB of the node.
        /// Takes into account the AABB's of all drawable 
        /// objects for all children nodes and merges them into 
        /// one AABB.  Potentially useful for culling algorithms.
        /// </summary>
        /// <returns>Merged AABB</returns>
        public virtual gxtAABB GetAABB()
        {
            Vector2 pos = GetDerivedPosition();
            Vector2 s = GetDerivedScale();
            float r = GetDerivedRotation();

            gxtAABB aabb = new gxtAABB(pos, Vector2.Zero);
            gxtAABB curDrawableAABB;
            int i;
            for (i = 0; i < NumDrawables; ++i)
            {
                curDrawableAABB = drawables[i].GetLocalAABB();
                curDrawableAABB = curDrawableAABB.GetRotatedAABB(r);
                curDrawableAABB = gxtAABB.Update(relativePosition, relativeRotation, curDrawableAABB);
                curDrawableAABB = new gxtAABB(pos, new Vector2(gxtMath.Abs(curDrawableAABB.Extents.X * s.X), gxtMath.Abs(curDrawableAABB.Extents.Y * s.Y)));
                aabb = gxtAABB.Merge(aabb, curDrawableAABB);
            }

            for (i = 0; i < NumChildrenNodes; ++i)
            {
                aabb = gxtAABB.Merge(children[i].GetAABB(), aabb);
            }

            return aabb;
        }
Esempio n. 9
0
        /*
        private static float CalculateArea(IEnumerator<Vector2> ptSet, Vector2 pt)
        {
                float minE = 0.0f, minEperp = 0.0f, maxE = 0.0f, maxEperp = 0.0f;
                ptSet.Reset();
                while (ptSet.MoveNext())
                {
                    Vector2 diff = ptSet.Current - prev;
                    // Project along edge axis
                    // Store min and max scalar projections on this axis
                    float dot = Vector2.Dot(diff, e);
                    if (dot < minE) minE = dot;
                    if (dot > maxE) maxE = dot;
                    // Same for perpendicular axis
                    dot = Vector2.Dot(diff, ePerp);
                    if (dot < minEperp) minEperp = dot;
                    if (dot > maxEperp) maxEperp = dot;
                }

                // Calculate area of rectangle, compare to existing minimum
                float area = (maxE - minE) * (maxEperp - minEperp);
        }

        public static gxtOBB ComputeOBB(IEnumerator<Vector2> ptSet)
        {
            // Area comparison value
            float minArea = float.MaxValue;

            // Instantiates members of OBB
            Vector2 c = new Vector2();
            Vector2 r = new Vector2();
            Vector2 localX = new Vector2();
            Vector2 localY = new Vector2();

            while (ptSet.MoveNext())
            {
                Vector2 prev = ptSet.Current;
                ptSet.MoveNext();
                Vector2 cur = ptSet.Current;

                Vector2 e = cur - prev;
                e.Normalize();
                Vector2 ePerp = new Vector2(-e.Y, e.X);

                float minE = 0.0f, minEperp = 0.0f, maxE = 0.0f, maxEperp = 0.0f;
                ptSet.Reset();
                while (ptSet.MoveNext())
                {
                    Vector2 diff = ptSet.Current - prev;
                    // Project along edge axis
                    // Store min and max scalar projections on this axis
                    float dot = Vector2.Dot(diff, e);
                    if (dot < minE) minE = dot;
                    if (dot > maxE) maxE = dot;
                    // Same for perpendicular axis
                    dot = Vector2.Dot(diff, ePerp);
                    if (dot < minEperp) minEperp = dot;
                    if (dot > maxEperp) maxEperp = dot;
                }

                // Calculate area of rectangle, compare to existing minimum
                float area = (maxE - minE) * (maxEperp - minEperp);

                if (area < minArea)
                {
                    // Store new min
                    minArea = area;
                    // Like finding the center of an AABB
                    // Start with first edge point, project over to new maximum along each axis
                    // Divide by two
                    c = prev + 0.5f * ((minE + maxE) * e + (minEperp + maxEperp) * ePerp);
                    // Half-Width Extents
                    r = new Vector2((maxE - minE) * 0.5f, (maxEperp - minEperp) * 0.5f);
                    // New axes for the OBB
                    localX = e;
                    localY = ePerp;
                }
            }

            // Setting up the for loop this way avoids modulo and lets you iterate once smoothly
            for (int i = 0, j = ptSet.Length - 1; i < ptSet.Length; j = i, i++)
            {
                // Normalized edge axis
                Vector2 e = ptSet[i] - ptSet[j];
                e.Normalize();
                // Perpendicular edge axis
                Vector2 ePerp = new Vector2(-e.Y, e.X);

                // The min and max projections along the edge axis and its perpendicular axis
                float minE = 0.0f, minEperp = 0.0f, maxE = 0.0f, maxEperp = 0.0f;
                // Project all points along these two axes
                for (int k = 0; k < ptSet.Length; k++)
                {
                    Vector2 diff = ptSet[k] - ptSet[j];
                    // Project along edge axis
                    // Store min and max scalar projections on this axis
                    float dot = Vector2.Dot(diff, e);
                    if (dot < minE) minE = dot;
                    if (dot > maxE) maxE = dot;
                    // Same for perpendicular axis
                    dot = Vector2.Dot(diff, ePerp);
                    if (dot < minEperp) minEperp = dot;
                    if (dot > maxEperp) maxEperp = dot;
                }

                // Calculate area of rectangle, compare to existing minimum
                float area = (maxE - minE) * (maxEperp - minEperp);

                if (area < minArea)
                {
                    // Store new min
                    minArea = area;
                    // Like finding the center of an AABB
                    // Start with first edge point, project over to new maximum along each axis
                    // Divide by two
                    c = ptSet[j] + 0.5f * ((minE + maxE) * e + (minEperp + maxEperp) * ePerp);
                    // Half-Width Extents
                    r = new Vector2((maxE - minE) * 0.5f, (maxEperp - minEperp) * 0.5f);
                    // New axes for the OBB
                    localX = e;
                    localY = ePerp;
                }
            }

            return new gxtOBB(c, r, localX, localY);
        }
        */
        /// <summary>
        /// Converts an AABB to a valid polygon with 4 vertices
        /// </summary>
        /// <param name="aabb">AABB</param>
        /// <returns>Polygon</returns>
        public static gxtPolygon ComputePolygonFromAABB(gxtAABB aabb)
        {
            return new gxtPolygon(ComputeVerticesFromAABB(aabb));
        }
Esempio n. 10
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sphere"></param>
        /// <param name="hitGeoms"></param>
        /// <param name="collisionGroup"></param>
        /// <returns></returns>
        public bool SphereCastAll(gxtSphere sphere, out List<gxtGeom> hitGeoms, gxtCollisionGroup collisionGroup = gxtCollisionGroup.ALL)
        {
            if (collisionGroup == gxtCollisionGroup.NONE)
            {
                hitGeoms = new List<gxtGeom>();
                return false;
            }

            // we pass an aabb of the sphere thru the broadphase collider...for now
            // narrowphase tests use the actual sphere
            gxtAABB aabb = new gxtAABB(sphere.Position, new Vector2(sphere.Radius));
            hitGeoms = broadphaseCollider.AABBCastAll(aabb);

            if (hitGeoms.Count == 0)
                return false;

            gxtPolygon geomPolygon;
            for (int i = hitGeoms.Count - 1; i >= 0; i--)
            {
                if (!CanCollide(collisionGroup, hitGeoms[i]))
                    hitGeoms.RemoveAt(i);
                else
                {
                    geomPolygon = hitGeoms[i].Polygon;
                    // must ue the guranteed world centroid to ensure an accurate test
                    // http://www.gamedev.net/topic/308060-circle-polygon-intersection-more-2d-collisions/
                    if (!gxtGJKCollider.Intersects(ref geomPolygon, hitGeoms[i].GetWorldCentroid(), sphere))
                        hitGeoms.RemoveAt(i);
                }
            }

            return hitGeoms.Count != 0;
        }
Esempio n. 11
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="aabb"></param>
 /// <param name="hitGeoms"></param>
 /// <param name="collisionGroupName"></param>
 /// <returns></returns>
 public bool AABBCastAll(gxtAABB aabb, out List<gxtGeom> hitGeoms, string collisionGroupName)
 {
     gxtDebug.Assert(collisionGroupsMap.ContainsKey(collisionGroupName), "Named Collision Group: {0} Does Not Exist In Physics World");
     gxtCollisionGroup cgroup = collisionGroupsMap[collisionGroupName];
     return AABBCastAll(aabb, out hitGeoms, cgroup);
 }
Esempio n. 12
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="aabb"></param>
        /// <param name="hitGeoms"></param>
        /// <param name="collisionGroup"></param>
        /// <returns></returns>
        public bool AABBCastAll(gxtAABB aabb, out List<gxtGeom> hitGeoms, gxtCollisionGroup collisionGroup = gxtCollisionGroup.ALL)
        {
            gxtDebug.Assert(aabb.Extents.X >= 0.0f && aabb.Extents.Y >= 0.0f, "An AABB with negative extents will not intersect anything");

            if (collisionGroup == gxtCollisionGroup.NONE)
            {
                hitGeoms = new List<gxtGeom>();
                return false;
            }

            hitGeoms = broadphaseCollider.AABBCastAll(aabb);

            if (hitGeoms.Count == 0)
                return false;

            gxtPolygon boxPolygon = gxtGeometry.ComputePolygonFromAABB(aabb);
            gxtPolygon geomPolygon;
            for (int i = hitGeoms.Count - 1; i >= 0; i--)
            {
                if (!CanCollide(collisionGroup, hitGeoms[i]))
                    hitGeoms.RemoveAt(i);
                else
                {
                    geomPolygon = hitGeoms[i].Polygon;
                    if (!gxtGJKCollider.Intersects(ref boxPolygon, aabb.Position, ref geomPolygon, hitGeoms[i].Position))
                        hitGeoms.RemoveAt(i);
                }
            }

            return hitGeoms.Count != 0;
        }
Esempio n. 13
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="aabb"></param>
 /// <param name="hitGeom"></param>
 /// <param name="collisionGroup"></param>
 /// <returns></returns>
 public bool AABBCast(gxtAABB aabb, out gxtGeom hitGeom, gxtCollisionGroup collisionGroup = gxtCollisionGroup.ALL)
 {
     hitGeom = null;
     List<gxtGeom> geoms;
     if (AABBCastAll(aabb, out geoms, collisionGroup))
     {
         float minDist = float.MaxValue;
         float tmpDist;
         for (int i = 0; i < geoms.Count; i++)
         {
             tmpDist = (aabb.Position - geoms[i].GetWorldCentroid()).LengthSquared();
             if (tmpDist < minDist)
             {
                 hitGeom = geoms[i];
                 minDist = tmpDist;
             }
         }
         return true;
     }
     return false;
 }
Esempio n. 14
0
        /// <summary>
        /// Gets the AABB of the camera
        /// </summary>
        /// <returns></returns>
        public virtual gxtAABB GetViewAABB()
        {
            Vector2 r = halfWidthScreenExtents;
            float s = 1.0f / (screenScale + zoom);
            r *= s;
            gxtAABB scaledAABB = new gxtAABB(position, r);

            scaledAABB = scaledAABB.GetRotatedAABB(rotation);
            return scaledAABB;
        }
Esempio n. 15
0
 public gxtAABB GetAABB(Vector2 position, float rotation, Vector2 scale)
 {
     float rX = gxtMath.Abs(Origin.X * scale.X);
     float rY = gxtMath.Abs(Origin.Y * scale.Y);
     gxtAABB aabb = new gxtAABB(Vector2.Zero, new Vector2(rX, rY));
     aabb = aabb.GetRotatedAABB(rotation);
     aabb.Translate(position);
     return aabb;
 }
Esempio n. 16
0
        public void SetVertices(Vector2[] verts, bool setDefaultIndices = true)
        {
            // overwrite the existing vertices
            vertices = new VertexPositionColorTexture[verts.Length];

            Color overlay = (material != null) ? material.ColorOverlay : gxtMaterial.DEFAULT_COLOR_OVERLAY;
            for (int i = 0; i < verts.Length; ++i)
            {
                vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), overlay, Vector2.Zero);
            }
            this.localAABB = gxtGeometry.ComputeAABB(verts);

            if (setDefaultIndices)
            {
                indices = new int[verts.Length];
                for (int i = 0; i < indices.Length; ++i)
                {
                    indices[i] = i;
                }
                this.primitiveCount = indices.Length / 2;
            }
        }
Esempio n. 17
0
        public void SetVertices(Vector2[] verts, bool setDefaultIndices = true)
        {
            // overwrite the existing vertices
            vertices = new VertexPositionColorTexture[verts.Length];
            if (vertexBuffer == null)
                vertexBuffer = new VertexBuffer(gxtRoot.Singleton.Graphics, typeof(VertexPositionColorTexture), verts.Length, BufferUsage.WriteOnly);

            Color overlay = (material != null) ? material.ColorOverlay : gxtMaterial.DEFAULT_COLOR_OVERLAY;
            for (int i = 0; i < verts.Length; ++i)
            {
                vertices[i] = new VertexPositionColorTexture(new Vector3(verts[i].X, verts[i].Y, 0.0f), overlay, Vector2.Zero);
            }
            vertexBuffer.SetData<VertexPositionColorTexture>(vertices);
            this.localAABB = gxtGeometry.ComputeAABB(verts);

            if (setDefaultIndices)
            {
                indices = new int[verts.Length];
                for (int i = 0; i < indices.Length; ++i)
                {
                    indices[i] = i;
                }

                if (indexBuffer == null)
                        indexBuffer = new IndexBuffer(gxtRoot.Singleton.Graphics, typeof(int), indices.Length, BufferUsage.WriteOnly);
                indexBuffer.SetData<int>(indices);
                this.primitiveCount = indices.Length / 2;
            }
        }
Esempio n. 18
0
 public gxtDynamicIndexedPrimitive(Vector2[] verts, int[] indices, PrimitiveType primitiveType, int primitiveCount)
 {
     this.primitiveType = primitiveType;
     this.primitiveCount = primitiveCount;
     SetupVertices(verts);
     SetupIndices(indices);
     localAABB = gxtGeometry.ComputeAABB(verts);
 }
Esempio n. 19
0
        /// <summary>
        /// Equivalent to ComputePolygonFromAABB() but returns the data 
        /// as an array of vertices instead
        /// </summary>
        /// <param name="aabb"></param>
        /// <returns></returns>
        public static Vector2[] ComputeVerticesFromAABB(gxtAABB aabb)
        {
            Vector2[] verts = new Vector2[4];

            Vector2 c = aabb.Position;
            Vector2 r = aabb.Extents;

            verts[0] = c - r;
            verts[1] = c + new Vector2(-r.X, r.Y);
            verts[2] = c + r;
            verts[3] = c + new Vector2(r.X, -r.Y);

            return verts;
        }
Esempio n. 20
0
 public void Draw(ref SpriteBatch spriteBatch, gxtAABB cameraAABB)
 {
     // brute force culling, for now
     for (int i = 0; i < drawableList.Count; i++)
     {
         if (gxtAABB.Intersects(cameraAABB, drawableList[i].GetAABB()))
             drawableList[i].Draw(ref spriteBatch);
     }
 }