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)); }
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); }
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(); } }
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); }
[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)); }
/// <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)); }
/// <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); }
/// <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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
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); }