コード例 #1
0
ファイル: Minelayer.cs プロジェクト: CH4Code/OpenRA
        public Minelayer(Actor self)
        {
            this.self = self;

            var tileset = self.World.Map.Tileset.ToLowerInvariant();
            tile = self.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
        }
コード例 #2
0
ファイル: Minelayer.cs プロジェクト: Generalcamo/OpenRA
        public Minelayer(Actor self)
        {
            this.self = self;

            var tileset = self.World.TileSet.Id.ToLower();
            tile = SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
        }
コード例 #3
0
		public void Init(Manifest m, Dictionary<string, string> info)
		{
			var sheet = new Sheet(SheetType.BGRA, info["Image"]);
			var res = Game.Renderer.Resolution;
			bounds = new Rectangle(0, 0, res.Width, res.Height);
			sprite = new Sprite(sheet, new Rectangle(0, 0, 1024, 480), TextureChannel.Alpha);
		}
コード例 #4
0
ファイル: Util.cs プロジェクト: RunCraze/OpenRA
        public static void FastCopyIntoSprite(Sprite dest, Bitmap src)
        {
            var destStride = dest.sheet.Size.Width;
            var width = dest.bounds.Width;
            var height = dest.bounds.Height;

            var srcData = src.LockBits(src.Bounds(),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                var c = (int*)srcData.Scan0;

                // Cast the data to an int array so we can copy the src data directly
                fixed (byte* bd = &dest.sheet.Data[0])
                {
                    var data = (int*)bd;
                    var x = dest.bounds.Left;
                    var y = dest.bounds.Top;

                    for (var j = 0; j < height; j++)
                        for (var i = 0; i < width; i++)
                            data[(y + j) * destStride + x + i] = *(c + (j * srcData.Stride >> 2) + i);
                }
            }

            src.UnlockBits(srcData);
        }
コード例 #5
0
ファイル: CncLoadScreen.cs プロジェクト: Roger-luo/OpenRA
		public override void Init(Manifest m, Dictionary<string, string> info)
		{
			loadInfo = info;

			// Avoid standard loading mechanisms so we
			// can display loadscreen as early as possible
			r = Game.Renderer;
			if (r == null) return;

			sheet = new Sheet(SheetType.BGRA, Platform.ResolvePath(loadInfo["Image"]));
			var res = r.Resolution;
			bounds = new Rectangle(0, 0, res.Width, res.Height);

			borderTop = new Sprite(sheet, new Rectangle(161, 128, 62, 33), TextureChannel.Alpha);
			borderBottom = new Sprite(sheet, new Rectangle(161, 223, 62, 33), TextureChannel.Alpha);
			borderLeft = new Sprite(sheet, new Rectangle(128, 161, 33, 62), TextureChannel.Alpha);
			borderRight = new Sprite(sheet, new Rectangle(223, 161, 33, 62), TextureChannel.Alpha);
			cornerTopLeft = new Sprite(sheet, new Rectangle(128, 128, 33, 33), TextureChannel.Alpha);
			cornerTopRight = new Sprite(sheet, new Rectangle(223, 128, 33, 33), TextureChannel.Alpha);
			cornerBottomLeft = new Sprite(sheet, new Rectangle(128, 223, 33, 33), TextureChannel.Alpha);
			cornerBottomRight = new Sprite(sheet, new Rectangle(223, 223, 33, 33), TextureChannel.Alpha);

			nodLogo = new Sprite(sheet, new Rectangle(0, 256, 256, 256), TextureChannel.Alpha);
			gdiLogo = new Sprite(sheet, new Rectangle(256, 256, 256, 256), TextureChannel.Alpha);
			evaLogo = new Sprite(sheet, new Rectangle(256, 64, 128, 64), TextureChannel.Alpha);
			nodPos = new float2(bounds.Width / 2 - 384, bounds.Height / 2 - 128);
			gdiPos = new float2(bounds.Width / 2 + 128, bounds.Height / 2 - 128);
			evaPos = new float2(bounds.Width - 43 - 128, 43);

			brightBlock = new Sprite(sheet, new Rectangle(320, 0, 16, 35), TextureChannel.Alpha);
			dimBlock = new Sprite(sheet, new Rectangle(336, 0, 16, 35), TextureChannel.Alpha);

			versionText = m.Mod.Version;
		}
コード例 #6
0
 public void Init(Manifest m, Dictionary<string, string> info)
 {
     var sheet = new Sheet("mods/modchooser/chrome.png");
     var res = Game.Renderer.Resolution;
     bounds = new Rectangle(0, 0, res.Width, res.Height);
     sprite = new Sprite(sheet, new Rectangle(0,0,1024,480), TextureChannel.Alpha);
 }
コード例 #7
0
ファイル: VoxelRenderer.cs プロジェクト: Berzeger/OpenRA
		public VoxelRenderProxy(Sprite sprite, Sprite shadowSprite, float2[] projectedShadowBounds, float shadowDirection)
		{
			Sprite = sprite;
			ShadowSprite = shadowSprite;
			ProjectedShadowBounds = projectedShadowBounds;
			ShadowDirection = shadowDirection;
		}
コード例 #8
0
ファイル: RadarWidget.cs プロジェクト: JackKucan/OpenRA
		public override void Initialize(WidgetArgs args)
		{
			base.Initialize(args);

			var width = world.Map.Bounds.Width;
			var height = world.Map.Bounds.Height;
			var size = Math.Max(width, height);
			var rb = RenderBounds;

			previewScale = Math.Min(rb.Width * 1f / width, rb.Height * 1f / height);
			previewOrigin = new int2((int)(previewScale * (size - width) / 2), (int)(previewScale * (size - height) / 2));
			mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * width), (int)(previewScale * height));

			// Only needs to be done once
			using (var terrainBitmap = Minimap.TerrainBitmap(world.Map.Rules.TileSets[world.Map.Tileset], world.Map))
			{
				var r = new Rectangle(0, 0, width, height);
				var s = new Size(terrainBitmap.Width, terrainBitmap.Height);
				var terrainSheet = new Sheet(s, false);
				terrainSheet.Texture.SetData(terrainBitmap);
				terrainSprite = new Sprite(terrainSheet, r, TextureChannel.Alpha);

				// Data is set in Tick()
				customTerrainSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
				actorSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
				shroudSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
			}
		}
コード例 #9
0
ファイル: Util.cs プロジェクト: RunCraze/OpenRA
 public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, int palette, int nv, float2 size)
 {
     var b = new float2(o.X + size.X, o.Y);
     var c = new float2(o.X + size.X, o.Y + size.Y);
     var d = new float2(o.X, o.Y + size.Y);
     FastCreateQuad(vertices, o, b, c, d, r, palette, nv);
 }
コード例 #10
0
        public TerrainSpriteLayer(World world, WorldRenderer wr, Sheet sheet, BlendMode blendMode, PaletteReference palette, bool restrictToBounds)
        {
            worldRenderer = wr;
            this.restrictToBounds = restrictToBounds;
            Sheet = sheet;
            BlendMode = blendMode;
            paletteIndex = palette.TextureIndex;

            map = world.Map;
            rowStride = 4 * map.MapSize.X;

            vertices = new Vertex[rowStride * map.MapSize.Y];
            vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length);
            emptySprite = new Sprite(sheet, Rectangle.Empty, TextureChannel.Alpha);

            wr.PaletteInvalidated += () =>
            {
                paletteIndex = palette.TextureIndex;

                // Everything in the layer uses the same palette,
                // so we can fix the indices in one pass
                for (var i = 0; i < vertices.Length; i++)
                {
                    var v = vertices[i];
                    vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, paletteIndex, v.C);
                }

                for (var row = 0; row < map.MapSize.Y; row++)
                    dirtyRows.Add(row);
            };
        }
コード例 #11
0
        public PlaceBuildingOrderGenerator(ProductionQueue queue, string name)
        {
            var world = queue.Actor.World;
            this.queue = queue;
            placeBuildingInfo = queue.Actor.Owner.PlayerActor.Info.TraitInfo<PlaceBuildingInfo>();
            building = name;

            // Clear selection if using Left-Click Orders
            if (Game.Settings.Game.UseClassicMouseStyle)
                world.Selection.Clear();

            var map = world.Map;
            var tileset = world.Map.Tileset.ToLowerInvariant();

            var info = map.Rules.Actors[building];
            buildingInfo = info.TraitInfo<BuildingInfo>();

            var buildableInfo = info.TraitInfo<BuildableInfo>();
            var mostLikelyProducer = queue.MostLikelyProducer();
            faction = buildableInfo.ForceFaction
                ?? (mostLikelyProducer.Trait != null ? mostLikelyProducer.Trait.Faction : queue.Actor.Owner.Faction.InternalName);

            buildOk = map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
            buildBlocked = map.Rules.Sequences.GetSequence("overlay", "build-invalid").GetSprite(0);

            buildingInfluence = world.WorldActor.Trait<BuildingInfluence>();
        }
コード例 #12
0
ファイル: SpriteWidget.cs プロジェクト: Roger-luo/OpenRA
		public override void Draw()
		{
			var sprite = GetSprite();
			var palette = GetPalette();
			var scale = GetScale();

			if (sprite == null || palette == null)
				return;

			if (sprite != cachedSprite)
			{
				offset = 0.5f * (new float2(RenderBounds.Size) - sprite.Size);
				cachedSprite = sprite;
			}

			if (palette != cachedPalette)
			{
				pr = WorldRenderer.Palette(palette);
				cachedPalette = palette;
			}

			if (scale != cachedScale)
			{
				offset *= scale;
				cachedScale = scale;
			}

			var size = new float2(sprite.Size.X * scale, sprite.Size.Y * scale);
			Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + offset, pr, size);
		}
コード例 #13
0
ファイル: Theater.cs プロジェクト: RobotCaleb/OpenRA
        public Theater(TileSet tileset)
        {
            var allocated = false;
            Func<Sheet> allocate = () =>
            {
                if (allocated)
                    throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
                allocated = true;

                return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true);
            };

            sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
            templates = new Dictionary<ushort, Sprite[]>();

            var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions);
            foreach (var t in tileset.Templates)
            {
                var allFrames = frameCache[t.Value.Image];
                var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames;
                templates.Add(t.Value.Id, frames.Select(f => sheetBuilder.Add(f)).ToArray());
            }

            // 1x1px transparent tile
            missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));

            Sheet.ReleaseBuffer();
        }
コード例 #14
0
ファイル: ShroudRenderer.cs プロジェクト: nevelis/OpenRA
        public ShroudRenderer(World world)
        {
            this.world = world;
            this.map = world.Map;

            sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
            fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
        }
コード例 #15
0
 public UISpriteRenderable(Sprite sprite, int2 screenPos, int zOffset, PaletteReference palette, float scale)
 {
     this.sprite = sprite;
     this.screenPos = screenPos;
     this.zOffset = zOffset;
     this.palette = palette;
     this.scale = scale;
 }
コード例 #16
0
ファイル: IronCurtainPower.cs プロジェクト: JackKucan/OpenRA
			public SelectTarget(World world, string order, SupportPowerManager manager, IronCurtainPower power)
			{
				this.manager = manager;
				this.order = order;
				this.power = power;
				this.range = ((IronCurtainPowerInfo)power.Info).Range;
				tile = world.Map.SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
			}
コード例 #17
0
        public void AddTile(CPos cell, TerrainTile tile)
        {
            map.CustomTerrain[cell] = map.Rules.TileSet.GetTerrainIndex(tile);

            // Terrain tiles define their origin at the topleft
            var s = theater.TileSprite(tile);
            dirty[cell] = new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode);
        }
コード例 #18
0
        public ShroudRenderer(World world)
        {
            this.shroud = world.LocalShroud;
            this.map = world.Map;

            sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
            fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
            shroud.Dirty += () => dirty = true;
        }
コード例 #19
0
ファイル: WidgetUtils.cs プロジェクト: ushardul/OpenRA
        public static void DrawPanelPartial(Rectangle bounds, PanelSides ps,
			Sprite borderTop,
			Sprite borderBottom,
			Sprite borderLeft,
			Sprite borderRight,
			Sprite cornerTopLeft,
			Sprite cornerTopRight,
			Sprite cornerBottomLeft,
			Sprite cornerBottomRight,
			Sprite background)
        {
            var marginLeft = borderLeft == null ? 0 : (int)borderLeft.Size.X;
            var marginTop = borderTop == null ? 0 : (int)borderTop.Size.Y;
            var marginRight = borderRight == null ? 0 : (int)borderRight.Size.X;
            var marginBottom = borderBottom == null ? 0 : (int)borderBottom.Size.Y;
            var marginWidth = marginRight + marginLeft;
            var marginHeight = marginBottom + marginTop;

            // Background
            if (ps.HasFlags(PanelSides.Center) && background != null)
                FillRectWithSprite(new Rectangle(bounds.Left + marginLeft, bounds.Top + marginTop,
                    bounds.Width - marginWidth, bounds.Height - marginHeight),
                    background);

            // Left border
            if (ps.HasFlags(PanelSides.Left) && borderLeft != null)
                FillRectWithSprite(new Rectangle(bounds.Left, bounds.Top + marginTop,
                    marginLeft, bounds.Height - marginHeight),
                    borderLeft);

            // Right border
            if (ps.HasFlags(PanelSides.Right) && borderRight != null)
                FillRectWithSprite(new Rectangle(bounds.Right - marginRight, bounds.Top + marginTop,
                    marginLeft, bounds.Height - marginHeight),
                    borderRight);

            // Top border
            if (ps.HasFlags(PanelSides.Top) && borderTop != null)
                FillRectWithSprite(new Rectangle(bounds.Left + marginLeft, bounds.Top,
                    bounds.Width - marginWidth, marginTop),
                    borderTop);

            // Bottom border
            if (ps.HasFlags(PanelSides.Bottom) && borderBottom != null)
                FillRectWithSprite(new Rectangle(bounds.Left + marginLeft, bounds.Bottom - marginBottom,
                    bounds.Width - marginWidth, marginTop),
                    borderBottom);

            if (ps.HasFlags(PanelSides.Left | PanelSides.Top) && cornerTopLeft != null)
                DrawRGBA(cornerTopLeft, new float2(bounds.Left, bounds.Top));
            if (ps.HasFlags(PanelSides.Right | PanelSides.Top) && cornerTopRight != null)
                DrawRGBA(cornerTopRight, new float2(bounds.Right - cornerTopRight.Size.X, bounds.Top));
            if (ps.HasFlags(PanelSides.Left | PanelSides.Bottom) && cornerBottomLeft != null)
                DrawRGBA(cornerBottomLeft, new float2(bounds.Left, bounds.Bottom - cornerBottomLeft.Size.Y));
            if (ps.HasFlags(PanelSides.Right | PanelSides.Bottom) && cornerBottomRight != null)
                DrawRGBA(cornerBottomRight, new float2(bounds.Right - cornerBottomRight.Size.X, bounds.Bottom - cornerBottomRight.Size.Y));
        }
コード例 #20
0
ファイル: Util.cs プロジェクト: Berzeger/OpenRA
		public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, int palette, int nv)
		{
			var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);

			vertices[nv] = new Vertex(a, r.FastMapTextureCoords(0), attrib);
			vertices[nv + 1] = new Vertex(b, r.FastMapTextureCoords(1), attrib);
			vertices[nv + 2] = new Vertex(c, r.FastMapTextureCoords(3), attrib);
			vertices[nv + 3] = new Vertex(d, r.FastMapTextureCoords(2), attrib);
		}
コード例 #21
0
ファイル: MapPreviewWidget.cs プロジェクト: mgatland/OpenRA
        public override void DrawInner( World world )
        {
            if (UnownedSpawn == null)
                UnownedSpawn = ChromeProvider.GetImage("spawnpoints", "unowned");
            if (OwnedSpawn == null)
                OwnedSpawn = ChromeProvider.GetImage("spawnpoints", "owned");

            var map = Map();
            if( map == null ) return;

            if (lastMap != map)
            {
                lastMap = map;

                // Update image data
                var preview = PreviewCache[map];
                if( mapChooserSheet == null || mapChooserSheet.Size.Width != preview.Width || mapChooserSheet.Size.Height != preview.Height )
                    mapChooserSheet = new Sheet(new Size( preview.Width, preview.Height ) );

                mapChooserSheet.Texture.SetData( preview );
                mapChooserSprite = new Sprite( mapChooserSheet, new Rectangle( 0, 0, map.Width, map.Height ), TextureChannel.Alpha );

                // Update map rect
                PreviewScale = Math.Min(RenderBounds.Width * 1.0f / map.Width, RenderBounds.Height * 1.0f / map.Height);
                var size = Math.Max(map.Width, map.Height);
                var dw = (int)(PreviewScale * (size - map.Width)) / 2;
                var dh = (int)(PreviewScale * (size - map.Height)) / 2;
                MapRect = new Rectangle(RenderBounds.X + dw, RenderBounds.Y + dh, (int)(map.Width * PreviewScale), (int)(map.Height * PreviewScale));
            }

            Game.Renderer.RgbaSpriteRenderer.DrawSprite( mapChooserSprite,
                new float2(MapRect.Location),
                new float2( MapRect.Size ) );

            Game.Renderer.RgbaSpriteRenderer.Flush();

            // Overlay spawnpoints
            var colors = SpawnColors();
            foreach (var p in map.SpawnPoints)
            {
                var pos = ConvertToPreview(map, p);
                var sprite = UnownedSpawn;
                var offset = new int2(-UnownedSpawn.bounds.Width/2, -UnownedSpawn.bounds.Height/2);

                if (colors.ContainsKey(p))
                {
                    sprite = OwnedSpawn;
                    offset = new int2(-OwnedSpawn.bounds.Width/2, -OwnedSpawn.bounds.Height/2);
                    WidgetUtils.FillRectWithColor(new Rectangle(pos.X + offset.X + 2, pos.Y + offset.Y + 2, 12, 12), colors[p]);
                    Game.Renderer.LineRenderer.Flush();
                }
                Game.Renderer.RgbaSpriteRenderer.DrawSprite(sprite, pos + offset);
            }

            Game.Renderer.Flush();
        }
コード例 #22
0
ファイル: ShroudRenderer.cs プロジェクト: pdovy/OpenRA
        public ShroudRenderer(Player owner, Map map)
        {
            this.shroud = owner.World.WorldActor.Trait<Traits.Shroud>();
            this.map = map;

            sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
            fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];

            shroud.Dirty += () => dirty = true;
        }
コード例 #23
0
ファイル: Util.cs プロジェクト: RobotCaleb/OpenRA
        public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, int palette, int nv)
        {
            var attribP = palette / (float)HardwarePalette.MaxPalettes;
            var attribC = channelSelect[(int)r.channel];

            vertices[nv] = new Vertex(a, r.left, r.top, attribP, attribC);
            vertices[nv + 1] = new Vertex(b, r.right, r.top, attribP, attribC);
            vertices[nv + 2] = new Vertex(c, r.right, r.bottom, attribP, attribC);
            vertices[nv + 3] = new Vertex(d, r.left, r.bottom, attribP, attribC);
        }
コード例 #24
0
        public EditorSelectionLayer(Actor self, EditorSelectionLayerInfo info)
        {
            if (self.World.Type != WorldType.Editor)
                return;

            this.info = info;
            map = self.World.Map;
            copySprite = map.Rules.Sequences.GetSequence(info.Image, info.CopySequence).GetSprite(0);
            pasteSprite = map.Rules.Sequences.GetSequence(info.Image, info.PasteSequence).GetSprite(0);
        }
コード例 #25
0
ファイル: ColorMixerWidget.cs プロジェクト: CH4Code/OpenRA
		public void SetPaletteRange(float sMin, float sMax, float vMin, float vMax)
		{
			sRange[0] = sMin + STrim;
			sRange[1] = sMax - STrim;
			vRange[0] = vMin + VTrim;
			vRange[1] = vMax - VTrim;

			var rect = new Rectangle((int)(255 * sRange[0]), (int)(255 * (1 - vRange[1])), (int)(255 * (sRange[1] - sRange[0])) + 1, (int)(255 * (vRange[1] - vRange[0])) + 1);
			mixerSprite = new Sprite(mixerSprite.Sheet, rect, TextureChannel.Alpha);
		}
コード例 #26
0
        public PlaceBuildingOrderGenerator(Actor producer, string name)
        {
            Producer = producer;
            Building = name;
            var tileset = producer.World.TileSet.Id.ToLower();
            BuildingInfo = Rules.Info[Building].Traits.Get<BuildingInfo>();

            buildOk = SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
            buildBlocked = SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
        }
コード例 #27
0
ファイル: SpriteRenderable.cs プロジェクト: CH4Code/OpenRA
 public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration)
 {
     this.sprite = sprite;
     this.pos = pos;
     this.offset = offset;
     this.zOffset = zOffset;
     this.palette = palette;
     this.scale = scale;
     this.isDecoration = isDecoration;
 }
コード例 #28
0
ファイル: SpriteRenderer.cs プロジェクト: Roger-luo/OpenRA
		void SetRenderStateForSprite(Sprite s)
		{
			renderer.CurrentBatchRenderer = this;

			if (s.BlendMode != currentBlend || s.Sheet != currentSheet || nv + 4 > renderer.TempBufferSize)
				Flush();

			currentBlend = s.BlendMode;
			currentSheet = s.Sheet;
		}
コード例 #29
0
ファイル: MapPreviewWidget.cs プロジェクト: ushardul/OpenRA
        public MapPreviewWidget()
        {
            tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));

            spawnClaimed = ChromeProvider.GetImage("lobby-bits", "spawn-claimed");
            spawnUnclaimed = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed");
            spawnFont = Game.Renderer.Fonts[ChromeMetrics.Get<string>("SpawnFont")];
            spawnColor = ChromeMetrics.Get<Color>("SpawnColor");
            spawnContrastColor = ChromeMetrics.Get<Color>("SpawnContrastColor");
            spawnLabelOffset = ChromeMetrics.Get<int2>("SpawnLabelOffset");
        }
コード例 #30
0
ファイル: Util.cs プロジェクト: Roger-luo/OpenRA
		public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, float paletteTextureIndex, int nv)
		{
			var attribC = ChannelSelect[(int)r.Channel];
			if (r.Sheet.Type == SheetType.DualIndexed)
				attribC *= -1;

			vertices[nv] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC);
			vertices[nv + 1] = new Vertex(b, r.Right, r.Top, paletteTextureIndex, attribC);
			vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, paletteTextureIndex, attribC);
			vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, paletteTextureIndex, attribC);
		}