Пример #1
0
        private ShapeInfo PickShape(RigidBody body, Vector2 worldCoord)
        {
            // Special case for non-solid / "outline only" shapes, because they are by definition unpickable
            Rect worldRect = Rect.Align(Alignment.Center, worldCoord.X, worldCoord.Y, 10.0f, 10.0f);

            foreach (ShapeInfo shape in body.Shapes)
            {
                VertexBasedShapeInfo vertexShape = shape as VertexBasedShapeInfo;
                if (vertexShape == null)
                {
                    continue;
                }
                if ((vertexShape.ShapeTraits & VertexShapeTrait.IsSolid) != VertexShapeTrait.None)
                {
                    continue;
                }

                Vector2[] vertices = vertexShape.Vertices;
                if (vertices != null && IsOutlineBoxIntersection(body.GameObj.Transform, vertices, worldRect))
                {
                    return(shape);
                }
            }

            // Do a physical picking operation
            return(body.PickShape(worldCoord));
        }
        private ShapeInfo PickShape(RigidBody body, Vector2 worldCoord)
        {
            // Special case for Loop- and ChainShapes, because they are by definition unpickable
            Rect worldRect = Rect.Align(Alignment.Center, worldCoord.X, worldCoord.Y, 10.0f, 10.0f);

            foreach (ShapeInfo shape in body.Shapes)
            {
                LoopShapeInfo  loop  = shape as LoopShapeInfo;
                ChainShapeInfo chain = shape as ChainShapeInfo;

                Vector2[] vertices = null;
                if (loop != null)
                {
                    vertices = loop.Vertices;
                }
                if (chain != null)
                {
                    vertices = chain.Vertices;
                }

                if (vertices != null && IsOutlineBoxIntersection(body.GameObj.Transform, vertices, worldRect))
                {
                    return(shape);
                }
            }

            // Do a physical picking operation
            return(body.PickShape(worldCoord));
        }
Пример #3
0
        public Bullet CreateBullet()
        {
            GameObject     obj       = new GameObject("Bullet");
            Transform      transform = obj.AddComponent <Transform>();
            RigidBody      body      = obj.AddComponent <RigidBody>();
            SpriteRenderer sprite    = obj.AddComponent <SpriteRenderer>();
            Bullet         bullet    = obj.AddComponent <Bullet>();

            Material spriteMaterial = this.spriteMaterial.Res ?? Material.SolidWhite.Res;
            Vector2  spriteSize     = spriteMaterial.MainTexture.IsAvailable ? spriteMaterial.MainTexture.Res.Size : new Vector2(5, 5);
            float    spriteRadius   = MathF.Max(spriteSize.X, spriteSize.Y) * 0.25f;

            body.ClearShapes();
            CircleShapeInfo circleShape = new CircleShapeInfo(spriteRadius, Vector2.Zero, 1.0f);

            circleShape.IsSensor = true;
            body.AddShape(circleShape);
            body.CollisionCategory = CollisionCategory.Cat3;
            body.CollidesWith     &= ~CollisionCategory.Cat3;

            sprite.SharedMaterial = this.spriteMaterial;
            sprite.Rect           = Rect.Align(Alignment.Center, 0.0f, 0.0f, spriteSize.X * 0.5f, spriteSize.Y * 0.5f);

            bullet.InitFrom(this);

            return(bullet);
        }
Пример #4
0
        private void RenderSinglePass(Rect viewportRect, Pass p)
        {
            this.drawDevice.VisibilityMask = this.visibilityMask & p.VisibilityMask;
            this.drawDevice.RenderMode     = p.MatrixMode;
            this.drawDevice.Target         = p.Output;
            this.drawDevice.ViewportRect   = p.Output.IsAvailable ? new Rect(p.Output.Res.Width, p.Output.Res.Height) : viewportRect;

            if (p.Input == null)
            {
                // Render Scene
                this.drawDevice.PrepareForDrawcalls();
                try
                {
                    this.CollectDrawcalls();
                    p.NotifyCollectDrawcalls(this.drawDevice);
                }
                catch (Exception e)
                {
                    Log.Core.WriteError("There was an error while {0} was collecting drawcalls: {1}", this.ToString(), Log.Exception(e));
                }
                this.drawDevice.Render(p.ClearFlags, p.ClearColor, p.ClearDepth);
            }
            else
            {
                Profile.TimePostProcessing.BeginMeasure();
                this.drawDevice.PrepareForDrawcalls();

                Texture mainTex   = p.Input.MainTexture.Res;
                Vector2 uvRatio   = mainTex != null ? mainTex.UVRatio : Vector2.One;
                Vector2 inputSize = mainTex != null ? new Vector2(mainTex.PixelWidth, mainTex.PixelHeight) : Vector2.One;
                Rect    targetRect;
                if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor &&
                    !this.drawDevice.Target.IsAvailable)
                {
                    targetRect = Rect.Align(Alignment.Center, this.drawDevice.TargetSize.X * 0.5f, this.drawDevice.TargetSize.Y * 0.5f, inputSize.X, inputSize.Y);
                }
                else
                {
                    targetRect = new Rect(this.drawDevice.TargetSize);
                }

                IDrawDevice device = this.drawDevice;
                {
                    VertexC1P3T2[] vertices = new VertexC1P3T2[4];
                    vertices[0].Pos      = new Vector3(targetRect.LeftX, targetRect.TopY, 0.0f);
                    vertices[1].Pos      = new Vector3(targetRect.RightX, targetRect.TopY, 0.0f);
                    vertices[2].Pos      = new Vector3(targetRect.RightX, targetRect.BottomY, 0.0f);
                    vertices[3].Pos      = new Vector3(targetRect.LeftX, targetRect.BottomY, 0.0f);
                    vertices[0].TexCoord = new Vector2(0.0f, 0.0f);
                    vertices[1].TexCoord = new Vector2(uvRatio.X, 0.0f);
                    vertices[2].TexCoord = new Vector2(uvRatio.X, uvRatio.Y);
                    vertices[3].TexCoord = new Vector2(0.0f, uvRatio.Y);
                    device.AddVertices(p.Input, VertexMode.Quads, vertices);
                }

                this.drawDevice.Render(p.ClearFlags, p.ClearColor, p.ClearDepth);
                Profile.TimePostProcessing.EndMeasure();
            }
        }
Пример #5
0
        private GameObject CreateSprite(Vector3 pos, Material material)
        {
            GameObject     obj       = new GameObject("Sprite");
            Transform      transform = obj.AddComponent <Transform>();
            SpriteRenderer sprite    = obj.AddComponent <SpriteRenderer>();

            transform.Pos         = pos;
            transform.Angle       = this.random.NextFloat(MathF.RadAngle360);
            sprite.SharedMaterial = material;
            sprite.Rect           = Rect.Align(Alignment.Center, 0.0f, 0.0f, 64.0f, 64.0f);

            return(obj);
        }
Пример #6
0
        [Test] public void CreateAlignment()
        {
            Assert.AreEqual(new Rect(-5, -5, 10, 10), Rect.Align(Alignment.Center, 0, 0, 10, 10));

            Assert.AreEqual(new Rect(0, -5, 10, 10), Rect.Align(Alignment.Left, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(-10, -5, 10, 10), Rect.Align(Alignment.Right, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(-5, 0, 10, 10), Rect.Align(Alignment.Top, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(-5, -10, 10, 10), Rect.Align(Alignment.Bottom, 0, 0, 10, 10));

            Assert.AreEqual(new Rect(0, 0, 10, 10), Rect.Align(Alignment.TopLeft, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(-10, 0, 10, 10), Rect.Align(Alignment.TopRight, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(0, -10, 10, 10), Rect.Align(Alignment.BottomLeft, 0, 0, 10, 10));
            Assert.AreEqual(new Rect(-10, -10, 10, 10), Rect.Align(Alignment.BottomRight, 0, 0, 10, 10));
        }
Пример #7
0
        /// <summary>
        /// Return an axis-aligned Rect that contains the current viewport with the desired size.
        /// </summary>
        /// <param name="z">Z world-coordinate used to determine the extents of the viewport.</param>
        /// <param name="imageSize">Target size of the rendered image before adjusting it to fit the specified viewport.</param>
        /// <returns>An axis-aligned Rect that fits the viewport. Could be bigger if the Camera is not rotated in 90° increments.</returns>
        public Rect GetWorldViewportBounds(float z, Vector2 imageSize)
        {
            this.GetWorldViewportCorners(this.cameraBounds, z, imageSize);

            float minX = float.PositiveInfinity;
            float minY = float.PositiveInfinity;
            float maxX = float.NegativeInfinity;
            float maxY = float.NegativeInfinity;

            for (int i = 0; i < 4; i++)
            {
                Vector2 corner = this.cameraBounds[i];

                minX = MathF.Min(minX, corner.X);
                minY = MathF.Min(minY, corner.Y);
                maxX = MathF.Max(maxX, corner.X);
                maxY = MathF.Max(maxY, corner.Y);
            }

            return(Rect.Align(Alignment.TopLeft, minX, minY, maxX - minX, maxY - minY));
        }
Пример #8
0
        /// <summary>
        /// Generates a single drawcall that renders a fullscreen quad using the specified material.
        /// Assumes that the <see cref="DrawDevice"/> is set up to render in screen space.
        /// </summary>
        /// <param name="material"></param>
        /// <param name="resizeMode"></param>
        public void AddFullscreenQuad(BatchInfo material, TargetResize resizeMode)
        {
            Texture tex       = material.MainTexture.Res;
            Vector2 uvRatio   = tex != null ? tex.UVRatio : Vector2.One;
            Point2  inputSize = tex != null ? tex.ContentSize : Point2.Zero;

            // Fit the input material rect to the output size according to rendering step config
            Vector2 targetSize = resizeMode.Apply(inputSize, this.TargetSize);
            Rect    targetRect = Rect.Align(
                Alignment.Center,
                this.TargetSize.X * 0.5f,
                this.TargetSize.Y * 0.5f,
                targetSize.X,
                targetSize.Y);

            // Fit the target rect to actual pixel coordinates to avoid unnecessary filtering offsets
            targetRect.X = (int)targetRect.X;
            targetRect.Y = (int)targetRect.Y;
            targetRect.W = MathF.Ceiling(targetRect.W);
            targetRect.H = MathF.Ceiling(targetRect.H);

            VertexC1P3T2[] vertices = new VertexC1P3T2[4];

            vertices[0].Pos = new Vector3(targetRect.LeftX, targetRect.TopY, 0.0f);
            vertices[1].Pos = new Vector3(targetRect.RightX, targetRect.TopY, 0.0f);
            vertices[2].Pos = new Vector3(targetRect.RightX, targetRect.BottomY, 0.0f);
            vertices[3].Pos = new Vector3(targetRect.LeftX, targetRect.BottomY, 0.0f);

            vertices[0].TexCoord = new Vector2(0.0f, 0.0f);
            vertices[1].TexCoord = new Vector2(uvRatio.X, 0.0f);
            vertices[2].TexCoord = new Vector2(uvRatio.X, uvRatio.Y);
            vertices[3].TexCoord = new Vector2(0.0f, uvRatio.Y);

            vertices[0].Color = ColorRgba.White;
            vertices[1].Color = ColorRgba.White;
            vertices[2].Color = ColorRgba.White;
            vertices[3].Color = ColorRgba.White;

            this.AddVertices(material, VertexMode.Quads, vertices);
        }
Пример #9
0
        /// <summary>
        /// Determines the generated depth offset for the tile at the specified tile coordinates.
        /// This also inclues the renderers overall offset as specified in <see cref="DepthOffset"/>,
        /// but ignores all actual per-tile and tileset depth offsets. The specified tile position
        /// is considered virtual and does not have to be within the valid tile position range.
        /// </summary>
        /// <param name="tilePos">The index of the tile of which to calculate the depth offset.</param>
        /// <returns></returns>
        public float GetTileDepthOffsetAt(Point2 tilePos)
        {
            if (this.tileDepthMode == TileDepthOffsetMode.Flat)
            {
                return(this.offset);
            }

            Tilemap tilemap   = this.ActiveTilemap;
            Tileset tileset   = tilemap != null ? tilemap.Tileset.Res : null;
            Point2  tileCount = tilemap != null ? tilemap.Size : new Point2(1, 1);
            Vector2 tileSize  = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize;

            float depthPerTile      = -tileSize.Y * this.GameObj.Transform.Scale * this.tileDepthScale;
            float originDepthOffset = Rect.Align(this.origin, 0, 0, 0, tileCount.Y * depthPerTile).Y;

            if (this.tileDepthMode == TileDepthOffsetMode.World)
            {
                originDepthOffset += (this.GameObj.Transform.Pos.Y / (float)tileSize.Y) * depthPerTile;
            }

            return(this.offset + this.tileDepthOffset * depthPerTile + originDepthOffset + tilePos.Y * depthPerTile);
        }
Пример #10
0
        public override void Draw(IDrawDevice device)
        {
            Vector3 posTemp = this.GameObj.Transform.Pos;

            int count = this.spritePositions.Count;

            this.vertices.Count = count * 4;

            ColorRgba mainClr    = ColorRgba.White;
            Rect      spriteRect = Rect.Align(Alignment.Center, 0.0f, 0.0f, 64.0f, 64.0f);
            Rect      uvRect     = new Rect(this.sharedMaterial.MainTexture.Res.UVRatio);
            float     left       = uvRect.X;
            float     right      = uvRect.RightX;
            float     top        = uvRect.Y;
            float     bottom     = uvRect.BottomY;

            VertexC1P3T2[] vert  = this.vertices.Data;
            Vector3[]      pos   = this.spritePositions.Data;
            float[]        angle = this.spriteAngles.Data;
            for (int i = 0; i < count; i++)
            {
                Vector2 edge1 = spriteRect.TopLeft;
                Vector2 edge2 = spriteRect.BottomLeft;
                Vector2 edge3 = spriteRect.BottomRight;
                Vector2 edge4 = spriteRect.TopRight;

                Vector2 spriteXDot, spriteYDot;
                MathF.GetTransformDotVec(angle[i], out spriteXDot, out spriteYDot);

                MathF.TransformDotVec(ref edge1, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge2, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge3, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge4, ref spriteXDot, ref spriteYDot);

                vert[i * 4 + 0].Pos.X      = posTemp.X + (pos[i].X + edge1.X);
                vert[i * 4 + 0].Pos.Y      = posTemp.Y + (pos[i].Y + edge1.Y);
                vert[i * 4 + 0].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 0].TexCoord.X = left;
                vert[i * 4 + 0].TexCoord.Y = top;
                vert[i * 4 + 0].Color      = mainClr;

                vert[i * 4 + 1].Pos.X      = posTemp.X + (pos[i].X + edge2.X);
                vert[i * 4 + 1].Pos.Y      = posTemp.Y + (pos[i].Y + edge2.Y);
                vert[i * 4 + 1].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 1].TexCoord.X = left;
                vert[i * 4 + 1].TexCoord.Y = bottom;
                vert[i * 4 + 1].Color      = mainClr;

                vert[i * 4 + 2].Pos.X      = posTemp.X + (pos[i].X + edge3.X);
                vert[i * 4 + 2].Pos.Y      = posTemp.Y + (pos[i].Y + edge3.Y);
                vert[i * 4 + 2].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 2].TexCoord.X = right;
                vert[i * 4 + 2].TexCoord.Y = bottom;
                vert[i * 4 + 2].Color      = mainClr;

                vert[i * 4 + 3].Pos.X      = posTemp.X + (pos[i].X + edge4.X);
                vert[i * 4 + 3].Pos.Y      = posTemp.Y + (pos[i].Y + edge4.Y);
                vert[i * 4 + 3].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 3].TexCoord.X = right;
                vert[i * 4 + 3].TexCoord.Y = top;
                vert[i * 4 + 3].Color      = mainClr;
            }

            device.AddVertices(this.sharedMaterial, VertexMode.Quads, vert, this.vertices.Count);
        }
Пример #11
0
        private void GenerateGeometry()
        {
            Vector3 posTemp = this.GameObj.Transform.Pos;

            int count = this.spritePositions.Count;

            this.vertices.Count = count * 4;

            ColorRgba mainClr    = ColorRgba.White;
            Rect      spriteRect = Rect.Align(Alignment.Center, 0.0f, 0.0f, 64.0f, 64.0f);
            Rect      uvRect     = new Rect(this.sharedMaterial.MainTexture.Res.UVRatio);
            float     left       = uvRect.X;
            float     right      = uvRect.RightX;
            float     top        = uvRect.Y;
            float     bottom     = uvRect.BottomY;

            VertexC1P3T2[] vert  = this.vertices.Data;
            Vector3[]      pos   = this.spritePositions.Data;
            float[]        angle = this.spriteAngles.Data;
            for (int i = 0; i < count; i++)
            {
                Vector2 edge1 = spriteRect.TopLeft;
                Vector2 edge2 = spriteRect.BottomLeft;
                Vector2 edge3 = spriteRect.BottomRight;
                Vector2 edge4 = spriteRect.TopRight;

                Vector2 spriteXDot, spriteYDot;
                MathF.GetTransformDotVec(angle[i], out spriteXDot, out spriteYDot);

                MathF.TransformDotVec(ref edge1, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge2, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge3, ref spriteXDot, ref spriteYDot);
                MathF.TransformDotVec(ref edge4, ref spriteXDot, ref spriteYDot);

                vert[i * 4 + 0].Pos.X      = posTemp.X + (pos[i].X + edge1.X);
                vert[i * 4 + 0].Pos.Y      = posTemp.Y + (pos[i].Y + edge1.Y);
                vert[i * 4 + 0].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 0].TexCoord.X = left;
                vert[i * 4 + 0].TexCoord.Y = top;
                vert[i * 4 + 0].Color      = mainClr;

                vert[i * 4 + 1].Pos.X      = posTemp.X + (pos[i].X + edge2.X);
                vert[i * 4 + 1].Pos.Y      = posTemp.Y + (pos[i].Y + edge2.Y);
                vert[i * 4 + 1].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 1].TexCoord.X = left;
                vert[i * 4 + 1].TexCoord.Y = bottom;
                vert[i * 4 + 1].Color      = mainClr;

                vert[i * 4 + 2].Pos.X      = posTemp.X + (pos[i].X + edge3.X);
                vert[i * 4 + 2].Pos.Y      = posTemp.Y + (pos[i].Y + edge3.Y);
                vert[i * 4 + 2].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 2].TexCoord.X = right;
                vert[i * 4 + 2].TexCoord.Y = bottom;
                vert[i * 4 + 2].Color      = mainClr;

                vert[i * 4 + 3].Pos.X      = posTemp.X + (pos[i].X + edge4.X);
                vert[i * 4 + 3].Pos.Y      = posTemp.Y + (pos[i].Y + edge4.Y);
                vert[i * 4 + 3].Pos.Z      = posTemp.Z + pos[i].Z;
                vert[i * 4 + 3].TexCoord.X = right;
                vert[i * 4 + 3].TexCoord.Y = top;
                vert[i * 4 + 3].Color      = mainClr;
            }

            // Upload vertices to the GPU
            if (this.geometry == null)
            {
                this.geometry = new VertexBuffer();
            }
            this.geometry.LoadVertexData(vert, 0, count * 4);

            // Prepare a static drawing batch we can re-use
            this.batch = new DrawBatch(
                this.geometry,
                new RawList <VertexDrawRange>()
            {
                new VertexDrawRange(0, count * 4)
            },
                VertexMode.Quads,
                this.sharedMaterial);
        }
Пример #12
0
        public override void Draw(IDrawDevice device)
        {
            // Determine basic working data
            Tilemap tilemap   = this.ActiveTilemap;
            Tileset tileset   = tilemap != null ? tilemap.Tileset.Res : null;
            Point2  tileCount = tilemap != null ? tilemap.Size : new Point2(1, 1);
            Vector2 tileSize  = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize;

            // Early-out, if insufficient
            if (tilemap == null)
            {
                return;
            }
            if (tileset == null)
            {
                return;
            }

            // Determine the total size and origin of the rendered Tilemap
            Vector2 renderTotalSize = tileCount * tileSize;
            Vector2 renderOrigin    = Vector2.Zero;

            this.origin.ApplyTo(ref renderOrigin, ref renderTotalSize);
            MathF.TransformCoord(ref renderOrigin.X, ref renderOrigin.Y, this.GameObj.Transform.Angle, this.GameObj.Transform.Scale);

            // Determine Tile visibility
            TilemapCulling.TileInput cullingIn = new TilemapCulling.TileInput
            {
                // Remember: All these transform values are in world space
                TilemapPos   = this.GameObj.Transform.Pos + new Vector3(renderOrigin),
                TilemapScale = this.GameObj.Transform.Scale,
                TilemapAngle = this.GameObj.Transform.Angle,
                TileCount    = tileCount,
                TileSize     = tileSize
            };
            TilemapCulling.TileOutput cullingOut = TilemapCulling.GetVisibleTileRect(device, cullingIn);
            int renderedTileCount = cullingOut.VisibleTileCount.X * cullingOut.VisibleTileCount.Y;

            // Determine rendering parameters
            Material  material  = (tileset != null ? tileset.RenderMaterial : null) ?? Material.Checkerboard.Res;
            ColorRgba mainColor = material.MainColor * this.colorTint;

            // Reserve the required space for vertex data in our locally cached buffer
            if (this.vertices == null)
            {
                this.vertices = new RawList <VertexC1P3T2>();
            }
            this.vertices.Count = renderedTileCount * 4;
            VertexC1P3T2[] vertexData = this.vertices.Data;

            // Determine and adjust data for Z offset generation
            float depthPerTile = -cullingIn.TileSize.Y * cullingIn.TilemapScale * this.tileDepthScale;

            if (this.tileDepthMode == TileDepthOffsetMode.Flat)
            {
                depthPerTile = 0.0f;
            }

            float originDepthOffset = Rect.Align(this.origin, 0, 0, 0, tileCount.Y * depthPerTile).Y;

            if (this.tileDepthMode == TileDepthOffsetMode.World)
            {
                originDepthOffset += (this.GameObj.Transform.Pos.Y / (float)tileSize.Y) * depthPerTile;
            }

            cullingOut.RenderOriginView.Z += this.offset + this.tileDepthOffset * depthPerTile + originDepthOffset;

            // Prepare vertex generation data
            Vector2 tileXStep   = cullingOut.XAxisView * cullingIn.TileSize.X;
            Vector2 tileYStep   = cullingOut.YAxisView * cullingIn.TileSize.Y;
            Vector3 renderPos   = cullingOut.RenderOriginView;
            Point2  tileGridPos = cullingOut.VisibleTileStart;

            // Prepare vertex data array for batch-submitting
            IReadOnlyGrid <Tile> tiles = tilemap.Tiles;

            TileInfo[] tileData           = tileset.TileData.Data;
            int        submittedTileCount = 0;
            int        vertexBaseIndex    = 0;

            for (int tileIndex = 0; tileIndex < renderedTileCount; tileIndex++)
            {
                Tile tile = tiles[tileGridPos.X, tileGridPos.Y];
                if (tile.Index < tileData.Length)
                {
                    Rect  uvRect           = tileData[tile.Index].TexCoord0;
                    bool  visualEmpty      = tileData[tile.Index].IsVisuallyEmpty;
                    int   tileBaseOffset   = tileData[tile.Index].DepthOffset;
                    float localDepthOffset = (tile.DepthOffset + tileBaseOffset) * depthPerTile;

                    if (!visualEmpty)
                    {
                        vertexData[vertexBaseIndex + 0].Pos.X      = renderPos.X;
                        vertexData[vertexBaseIndex + 0].Pos.Y      = renderPos.Y;
                        vertexData[vertexBaseIndex + 0].Pos.Z      = renderPos.Z + localDepthOffset;
                        vertexData[vertexBaseIndex + 0].TexCoord.X = uvRect.X;
                        vertexData[vertexBaseIndex + 0].TexCoord.Y = uvRect.Y;
                        vertexData[vertexBaseIndex + 0].Color      = mainColor;

                        vertexData[vertexBaseIndex + 1].Pos.X      = renderPos.X + tileYStep.X;
                        vertexData[vertexBaseIndex + 1].Pos.Y      = renderPos.Y + tileYStep.Y;
                        vertexData[vertexBaseIndex + 1].Pos.Z      = renderPos.Z + localDepthOffset + depthPerTile;
                        vertexData[vertexBaseIndex + 1].TexCoord.X = uvRect.X;
                        vertexData[vertexBaseIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H;
                        vertexData[vertexBaseIndex + 1].Color      = mainColor;

                        vertexData[vertexBaseIndex + 2].Pos.X      = renderPos.X + tileXStep.X + tileYStep.X;
                        vertexData[vertexBaseIndex + 2].Pos.Y      = renderPos.Y + tileXStep.Y + tileYStep.Y;
                        vertexData[vertexBaseIndex + 2].Pos.Z      = renderPos.Z + localDepthOffset + depthPerTile;
                        vertexData[vertexBaseIndex + 2].TexCoord.X = uvRect.X + uvRect.W;
                        vertexData[vertexBaseIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H;
                        vertexData[vertexBaseIndex + 2].Color      = mainColor;

                        vertexData[vertexBaseIndex + 3].Pos.X      = renderPos.X + tileXStep.X;
                        vertexData[vertexBaseIndex + 3].Pos.Y      = renderPos.Y + tileXStep.Y;
                        vertexData[vertexBaseIndex + 3].Pos.Z      = renderPos.Z + localDepthOffset;
                        vertexData[vertexBaseIndex + 3].TexCoord.X = uvRect.X + uvRect.W;
                        vertexData[vertexBaseIndex + 3].TexCoord.Y = uvRect.Y;
                        vertexData[vertexBaseIndex + 3].Color      = mainColor;

                        bool vertical = tileData[tile.Index].IsVertical;
                        if (vertical)
                        {
                            vertexData[vertexBaseIndex + 0].Pos.Z += depthPerTile;
                            vertexData[vertexBaseIndex + 3].Pos.Z += depthPerTile;
                        }

                        submittedTileCount++;
                        vertexBaseIndex += 4;
                    }
                }

                tileGridPos.X++;
                renderPos.X += tileXStep.X;
                renderPos.Y += tileXStep.Y;
                if ((tileGridPos.X - cullingOut.VisibleTileStart.X) >= cullingOut.VisibleTileCount.X)
                {
                    tileGridPos.X = cullingOut.VisibleTileStart.X;
                    tileGridPos.Y++;
                    renderPos    = cullingOut.RenderOriginView;
                    renderPos.X += tileYStep.X * (tileGridPos.Y - cullingOut.VisibleTileStart.Y);
                    renderPos.Y += tileYStep.Y * (tileGridPos.Y - cullingOut.VisibleTileStart.Y);
                    renderPos.Z += tileGridPos.Y * depthPerTile;
                }
            }

            // Submit all the vertices as one draw batch
            device.AddVertices(
                material,
                VertexMode.Quads,
                vertexData,
                submittedTileCount * 4);

            Profile.AddToStat(@"Duality\Stats\Render\Tilemaps\NumTiles", renderedTileCount);
            Profile.AddToStat(@"Duality\Stats\Render\Tilemaps\NumVertices", submittedTileCount * 4);
        }
Пример #13
0
        void ICmpRenderer.Draw(IDrawDevice device)
        {
            Player player     = this.GameObj.ParentScene.FindComponent <Player>();
            Ship   playerShip = player.ControlTarget;

            Canvas canvas = new Canvas(device);

            canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White));

            ColorRgba baseColor    = ColorRgba.White.WithAlpha(this.displayedTeamColor.W);
            ColorRgba defaultColor = this.displayedTeamColor.ToColor().WithAlpha(1.0f) * baseColor;

            if (this.gameOverFade > 0.0f)
            {
                canvas.State.ColorTint = ColorRgba.Black.WithAlpha(this.gameOverFade);
                canvas.FillRect(0.0f, 0.0f, canvas.Width, canvas.Height);
            }

            if (baseColor.A == 0)
            {
                return;
            }
            canvas.State.ColorTint = defaultColor;

            // Health bar
            float healthBarHeight = 150;

            canvas.State.ColorTint = defaultColor * ColorRgba.Black.WithAlpha(0.25f);
            canvas.FillRect(
                10,
                canvas.Height - 10 - healthBarHeight,
                30,
                healthBarHeight);
            canvas.State.ColorTint = defaultColor;
            canvas.DrawRect(
                10,
                canvas.Height - 10 - healthBarHeight,
                30,
                healthBarHeight);
            canvas.FillRect(
                12,
                canvas.Height - 12 - (healthBarHeight - 4) * playerShip.Health,
                26,
                (healthBarHeight - 4) * playerShip.Health);

            // Energy bar
            float energyBarHeight = 150;

            canvas.FillRect(
                10 + 30 + 2,
                canvas.Height - 10 - energyBarHeight * playerShip.WeaponEnergy,
                5,
                energyBarHeight * playerShip.WeaponEnergy);

            // Radar
            float radarDisplayRadius = 100.0f;
            Rect  radarArea          = Rect.Align(
                Alignment.BottomRight,
                canvas.Width - 10,
                canvas.Height - 10,
                radarDisplayRadius * 2.0f,
                radarDisplayRadius * 2.0f);
            float radarRange = 2500.0f;

            canvas.State.ColorTint = defaultColor * ColorRgba.Black.WithAlpha(0.25f);
            canvas.FillOval(
                radarArea.X,
                radarArea.Y,
                radarArea.W,
                radarArea.H);
            foreach (SpawnPoint spawnpoint in player.GameObj.ParentScene.FindComponents <SpawnPoint>())
            {
                Vector3 relativePos   = spawnpoint.GameObj.Transform.Pos - playerShip.GameObj.Transform.Pos;
                Vector3 normalizedPos = relativePos / radarRange;
                if ((normalizedPos * radarDisplayRadius).Xy.Length > radarDisplayRadius - 6.0f)
                {
                    continue;
                }

                Vector2 posOnRadar = radarArea.Center + (normalizedPos * radarDisplayRadius).Xy;

                canvas.State.ColorTint = baseColor * spawnpoint.TeamColor * ColorRgba.Grey;
                canvas.FillCircle(posOnRadar.X, posOnRadar.Y, 6.0f);
            }
            foreach (Ship ship in player.GameObj.ParentScene.FindComponents <Ship>())
            {
                Vector3 relativePos   = ship.GameObj.Transform.Pos - playerShip.GameObj.Transform.Pos;
                Vector3 normalizedPos = relativePos / radarRange;
                if ((normalizedPos * radarDisplayRadius).Xy.Length > radarDisplayRadius - 3.0f)
                {
                    continue;
                }

                Vector2 posOnRadar = radarArea.Center + (normalizedPos * radarDisplayRadius).Xy;

                canvas.State.ColorTint = baseColor * ship.TeamColor;
                canvas.FillCircle(posOnRadar.X, posOnRadar.Y, 3.0f);
            }
            foreach (Laser laser in player.GameObj.ParentScene.FindComponents <Laser>())
            {
                Vector3 relativePos   = laser.GameObj.Transform.Pos - playerShip.GameObj.Transform.Pos;
                Vector3 normalizedPos = relativePos / radarRange;
                if (normalizedPos.Length > 1.0f)
                {
                    continue;
                }

                Vector2 posOnRadar = radarArea.Center + (normalizedPos * radarDisplayRadius).Xy;

                canvas.State.ColorTint = baseColor * laser.TeamColor;
                canvas.FillRect(posOnRadar.X, posOnRadar.Y, 1.0f, 1.0f);
            }
            canvas.State.ColorTint = defaultColor;
            canvas.DrawOval(
                radarArea.X,
                radarArea.Y,
                radarArea.W,
                radarArea.H);

            Vector2 diffToCenter          = -playerShip.GameObj.Transform.Pos.Xy;
            Vector2 dirToCenter           = diffToCenter.Normalized;
            float   centerIndicatorLength = MathF.Min(10.0f, 10.0f * diffToCenter.Length / 2000.0f);

            canvas.State.ColorTint = defaultColor * ColorRgba.White.WithAlpha(0.5f);
            canvas.DrawLine(
                radarArea.CenterX,
                radarArea.CenterY,
                radarArea.CenterX + dirToCenter.X * centerIndicatorLength,
                radarArea.CenterY + dirToCenter.Y * centerIndicatorLength);

            canvas.State.ColorTint = defaultColor;
            canvas.FillCircle(radarArea.CenterX, radarArea.CenterY, 3.0f);
        }
Пример #14
0
        public override bool Convert(ConvertOperation convert)
        {
            // If we already have a renderer in the result set, consider generating
            // another one to be not the right course of action.
            if (convert.Result.OfType <ICmpRenderer>().Any())
            {
                return(false);
            }

            List <object>   results   = new List <object>();
            List <Material> availData = convert.Perform <Material>().ToList();

            // Generate objects
            foreach (Material mat in availData)
            {
                if (convert.IsObjectHandled(mat))
                {
                    continue;
                }
                Texture    mainTex      = mat.MainTexture.Res;
                Pixmap     basePixmap   = (mainTex != null) ? mainTex.BasePixmap.Res : null;
                GameObject gameobj      = convert.Result.OfType <GameObject>().FirstOrDefault();
                bool       hasAnimation = (mainTex != null && basePixmap != null && basePixmap.Atlas != null && basePixmap.Atlas.Count > 0);

                // Determine the size of the displayed sprite
                Vector2 spriteSize;
                if (hasAnimation)
                {
                    Rect atlasRect = basePixmap.LookupAtlas(0);
                    spriteSize = atlasRect.Size;
                }
                else if (mainTex != null)
                {
                    spriteSize = mainTex.ContentSize;

                    // If we're dealing with default content, clamp sprite size to
                    // something easily visible in order to avoid 1x1 sprites for
                    // default White / Black or similar fallback textures.
                    if (mainTex.IsDefaultContent)
                    {
                        spriteSize = Vector2.Max(spriteSize, new Vector2(32.0f, 32.0f));
                    }
                }
                else
                {
                    spriteSize = Pixmap.Checkerboard.Res.Size;
                }

                // Create a sprite Component in any case
                SpriteRenderer sprite = convert.Result.OfType <SpriteRenderer>().FirstOrDefault();
                if (sprite == null && gameobj != null)
                {
                    sprite = gameobj.GetComponent <SpriteRenderer>();
                }
                if (sprite == null)
                {
                    sprite = new SpriteRenderer();
                }
                sprite.SharedMaterial = mat;
                sprite.Rect           = Rect.Align(Alignment.Center, 0.0f, 0.0f, spriteSize.X, spriteSize.Y);
                results.Add(sprite);

                // If we have animation data, create an animator component as well
                if (hasAnimation)
                {
                    SpriteAnimator animator = convert.Result.OfType <SpriteAnimator>().FirstOrDefault();
                    if (animator == null && gameobj != null)
                    {
                        animator = gameobj.GetComponent <SpriteAnimator>();
                    }
                    if (animator == null)
                    {
                        animator = new SpriteAnimator();
                    }
                    animator.AnimDuration = 5.0f;
                    animator.FrameCount   = basePixmap.Atlas.Count;
                    results.Add(animator);
                }

                convert.SuggestResultName(sprite, mat.Name);
                convert.MarkObjectHandled(mat);
            }

            convert.AddResult(results);
            return(false);
        }
Пример #15
0
        private void UpdateRigidBody(RigidBody body, int sectorX, int sectorY)
        {
            Sector sector = this.sectors[sectorX, sectorY];

            // Determine collision checksum
            this.tempCollisionData.Clear();
            int newChecksum = this.MergeCollisionData(sectorX, sectorY, this.tempCollisionData);

            // If it differs from our previous value, update collision shapes
            if (sector.Checksum != newChecksum)
            {
                // Clean up old shapes
                if (sector.Shapes != null)
                {
                    foreach (ShapeInfo shape in sector.Shapes)
                    {
                        body.RemoveShape(shape);
                    }
                    sector.Shapes.Clear();
                }
                else
                {
                    sector.Shapes = new List <ShapeInfo>();
                }

                // Generate new shapes
                {
                    // Determine general working data
                    Tilemap tilemap        = this.referenceTilemap;
                    Tileset tileset        = tilemap != null ? tilemap.Tileset.Res : null;
                    Vector2 tileSize       = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize;
                    Point2  sectorBaseTile = new Point2(
                        sectorX * SectorSize,
                        sectorY * SectorSize);
                    Vector2 sectorBasePos = sectorBaseTile * tileSize;

                    // Clear the temporary edge map first
                    this.tempEdgeMap.Clear();

                    // Populate the edge map with fence and block geometry
                    AddFenceCollisionEdges(this.tempCollisionData, this.tempEdgeMap);
                    AddBlockCollisionEdges(this.tempCollisionData, this.tempEdgeMap, sectorBaseTile, this.tileCount);
                    if (this.solidOuterEdges)
                    {
                        AddBorderCollisionEdges(this.tempEdgeMap, sectorBaseTile, this.tileCount);
                    }

                    // Now traverse the edge map and gradually create chain / loop
                    // shapes until all edges have been used.
                    Rect localRect = Rect.Align(this.origin, 0, 0, this.tileCount.X * tileSize.X, this.tileCount.Y * tileSize.Y);
                    GenerateCollisionShapes(this.tempEdgeMap, localRect.TopLeft + sectorBasePos, tileSize, this.roundedCorners, sector.Shapes);

                    // Add all the generated shapes to the target body
                    foreach (ShapeInfo shape in sector.Shapes)
                    {
                        body.AddShape(shape);
                        shape.Friction    = this.shapeFriction;
                        shape.Restitution = this.shapeRestitution;
                    }
                }
                sector.Checksum = newChecksum;
            }

            this.sectors[sectorX, sectorY] = sector;
        }
Пример #16
0
        public override bool Convert(ConvertOperation convert)
        {
            List <object>   results   = new List <object>();
            List <Material> availData = convert.Perform <Material>().ToList();

            // Generate objects
            foreach (Material mat in availData)
            {
                if (convert.IsObjectHandled(mat))
                {
                    continue;
                }

                DrawTechnique     tech      = mat.Technique.Res;
                LightingTechnique lightTech = tech as LightingTechnique;
                if (tech == null)
                {
                    continue;
                }

                bool isDynamicLighting = lightTech != null ||
                                         tech.PreferredVertexFormat == VertexC1P3T2A4.Declaration ||
                                         tech.PreferredVertexFormat == VertexC1P3T4A4A1.Declaration;
                if (!isDynamicLighting)
                {
                    continue;
                }

                Texture    mainTex    = mat.MainTexture.Res;
                Pixmap     basePixmap = (mainTex != null) ? mainTex.BasePixmap.Res : null;
                GameObject gameobj    = convert.Result.OfType <GameObject>().FirstOrDefault();

                if (mainTex == null || basePixmap == null || basePixmap.AnimFrames == 0)
                {
                    LightingSpriteRenderer sprite = convert.Result.OfType <LightingSpriteRenderer>().FirstOrDefault();
                    if (sprite == null && gameobj != null)
                    {
                        sprite = gameobj.GetComponent <LightingSpriteRenderer>();
                    }
                    if (sprite == null)
                    {
                        sprite = new LightingSpriteRenderer();
                    }
                    sprite.SharedMaterial = mat;
                    if (mainTex != null)
                    {
                        sprite.Rect = Rect.Align(Alignment.Center, 0.0f, 0.0f, mainTex.PixelWidth, mainTex.PixelHeight);
                    }
                    convert.SuggestResultName(sprite, mat.Name);
                    results.Add(sprite);
                }
                else
                {
                    LightingAnimSpriteRenderer sprite = convert.Result.OfType <LightingAnimSpriteRenderer>().FirstOrDefault();
                    if (sprite == null && gameobj != null)
                    {
                        sprite = gameobj.GetComponent <LightingAnimSpriteRenderer>();
                    }
                    if (sprite == null)
                    {
                        sprite = new LightingAnimSpriteRenderer();
                    }
                    sprite.SharedMaterial = mat;
                    sprite.Rect           = Rect.Align(Alignment.Center,
                                                       0.0f,
                                                       0.0f,
                                                       (mainTex.PixelWidth / basePixmap.AnimCols) - basePixmap.AnimFrameBorder * 2,
                                                       (mainTex.PixelHeight / basePixmap.AnimRows) - basePixmap.AnimFrameBorder * 2);
                    sprite.AnimDuration   = 5.0f;
                    sprite.AnimFrameCount = basePixmap.AnimFrames;
                    convert.SuggestResultName(sprite, mat.Name);
                    results.Add(sprite);
                }

                convert.MarkObjectHandled(mat);
            }

            convert.AddResult(results);
            return(false);
        }
Пример #17
0
        public override bool Convert(ConvertOperation convert)
        {
            // If we already have a renderer in the result set, consider generating
            // another one to be not the right course of action.
            if (convert.Result.OfType <ICmpRenderer>().Any())
            {
                return(false);
            }

            List <object>   results   = new List <object>();
            List <Material> availData = convert.Perform <Material>().ToList();

            // Generate objects
            foreach (Material mat in availData)
            {
                if (convert.IsObjectHandled(mat))
                {
                    continue;
                }
                Texture    mainTex    = mat.MainTexture.Res;
                Pixmap     basePixmap = (mainTex != null) ? mainTex.BasePixmap.Res : null;
                GameObject gameobj    = convert.Result.OfType <GameObject>().FirstOrDefault();

                if (mainTex == null || basePixmap == null || basePixmap.AnimFrames == 0)
                {
                    SpriteRenderer sprite = convert.Result.OfType <SpriteRenderer>().FirstOrDefault();
                    if (sprite == null && gameobj != null)
                    {
                        sprite = gameobj.GetComponent <SpriteRenderer>();
                    }
                    if (sprite == null)
                    {
                        sprite = new SpriteRenderer();
                    }
                    sprite.SharedMaterial = mat;
                    if (mainTex != null)
                    {
                        sprite.Rect = Rect.Align(Alignment.Center, 0.0f, 0.0f, mainTex.PixelWidth, mainTex.PixelHeight);
                    }
                    convert.SuggestResultName(sprite, mat.Name);
                    results.Add(sprite);
                }
                else
                {
                    AnimSpriteRenderer sprite = convert.Result.OfType <AnimSpriteRenderer>().FirstOrDefault();
                    if (sprite == null && gameobj != null)
                    {
                        sprite = gameobj.GetComponent <AnimSpriteRenderer>();
                    }
                    if (sprite == null)
                    {
                        sprite = new AnimSpriteRenderer();
                    }
                    sprite.SharedMaterial = mat;
                    sprite.Rect           = Rect.Align(Alignment.Center,
                                                       0.0f,
                                                       0.0f,
                                                       (mainTex.PixelWidth / basePixmap.AnimCols) - basePixmap.AnimFrameBorder * 2,
                                                       (mainTex.PixelHeight / basePixmap.AnimRows) - basePixmap.AnimFrameBorder * 2);
                    sprite.AnimDuration   = 5.0f;
                    sprite.AnimFrameCount = basePixmap.AnimFrames;
                    convert.SuggestResultName(sprite, mat.Name);
                    results.Add(sprite);
                }

                convert.MarkObjectHandled(mat);
            }

            convert.AddResult(results);
            return(false);
        }
Пример #18
0
        public override bool Convert(ConvertOperation convert)
        {
            // If we already have a renderer in the result set, consider generating
            // another one to be not the right course of action.
            if (convert.Result.OfType <ICmpRenderer>().Any())
            {
                return(false);
            }

            List <object>   results   = new List <object>();
            List <Material> availData = convert.Perform <Material>().ToList();

            // Generate objects
            foreach (Material mat in availData)
            {
                if (convert.IsObjectHandled(mat))
                {
                    continue;
                }

                DrawTechnique tech = mat.Technique.Res;
                if (tech == null)
                {
                    continue;
                }

                bool isDynamicLighting =
                    tech is LightingTechnique ||
                    tech.PreferredVertexFormat == VertexDynamicLighting.Declaration;
                if (!isDynamicLighting)
                {
                    continue;
                }

                Texture    mainTex      = mat.MainTexture.Res;
                Pixmap     basePixmap   = (mainTex != null) ? mainTex.BasePixmap.Res : null;
                GameObject gameobj      = convert.Result.OfType <GameObject>().FirstOrDefault();
                bool       hasAnimation = (mainTex != null && basePixmap != null && basePixmap.Atlas != null && basePixmap.Atlas.Count > 0);

                // Determine the size of the displayed sprite
                Vector2 spriteSize;
                if (hasAnimation)
                {
                    Rect atlasRect = basePixmap.LookupAtlas(0);
                    spriteSize = atlasRect.Size;
                }
                else if (mainTex != null)
                {
                    spriteSize = mainTex.ContentSize;
                }
                else
                {
                    spriteSize = Pixmap.Checkerboard.Res.Size;
                }

                // Create a sprite Component in any case
                LightingSpriteRenderer sprite = convert.Result.OfType <LightingSpriteRenderer>().FirstOrDefault();
                if (sprite == null && gameobj != null)
                {
                    sprite = gameobj.GetComponent <LightingSpriteRenderer>();
                }
                if (sprite == null)
                {
                    sprite = new LightingSpriteRenderer();
                }
                sprite.SharedMaterial = mat;
                sprite.Rect           = Rect.Align(Alignment.Center, 0.0f, 0.0f, spriteSize.X, spriteSize.Y);
                results.Add(sprite);

                // If we have animation data, create an animator component as well
                if (hasAnimation)
                {
                    SpriteAnimator animator = convert.Result.OfType <SpriteAnimator>().FirstOrDefault();
                    if (animator == null && gameobj != null)
                    {
                        animator = gameobj.GetComponent <SpriteAnimator>();
                    }
                    if (animator == null)
                    {
                        animator = new SpriteAnimator();
                    }
                    animator.AnimDuration = 5.0f;
                    animator.FrameCount   = basePixmap.Atlas.Count;
                    results.Add(animator);
                }

                convert.SuggestResultName(sprite, mat.Name);
                convert.MarkObjectHandled(mat);
            }

            convert.AddResult(results);
            return(false);
        }