Exemple #1
0
 public void DrawFrame()
 {
     _graphicsDevice.GraphicsDevice.Clear(_clearColor);
     _spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied);
     _componentRenderer.DrawFrame(_currentScene.Components);
     _spriteBatch.End();
 }
Exemple #2
0
        public void Begin(ISpriteBatch batch)
        {
            device.SetRenderTarget(target);
            device.Clear(screenConstants.BackgroundColor);

            batch.Begin();
        }
Exemple #3
0
        public void Render(ISpriteBatch spriteBatch, V2 cameraPosition)
        {
            spriteBatch.Begin();

            for (int i = 0; i < positionedWorldCells.Length; i++)
            {
                if (positionedWorldCells[i] == null)
                {
                    continue;
                }

                for (int j = 0; j < positionedWorldCells[i].Count; j++)
                {
                    var cell = positionedWorldCells[i][j];

                    if (cell.Tile == null)
                    {
                        continue;
                    }

                    spriteBatch.Draw(cell.Tile.Texture,
                                     new Rect(0, 0, TileWidth, TileHeight),
                                     new Rect((int)cell.Position.X, (int)cell.Position.Y, TileWidth, TileHeight),
                                     0f,
                                     baseDepth - ((i * 100) + j) * HeightRowDepthMod);

                    spriteBatch.DrawString(SysCore.SystemFont, cell.Position.X + ", " + cell.Position.Y, new V2(cell.Position.X, cell.Position.Y), new V4(255), 0f, 1f, 1f);
                }
            }

            spriteBatch.End();
        }
Exemple #4
0
        public void DrawStatus(ISpriteBatch spriteBatch, bool isPlayerExtant, int playerEnergy, decimal score, int livesLeft, bool isPaused, bool isGameRunningSlowly)
        {
            spriteBatch.Begin();

            if (!isPaused)
            {
                UpdateDisplayValues(playerEnergy, score);
            }

            DrawEnergyRect(spriteBatch, isGameRunningSlowly);
            if (isPlayerExtant)
            {
                DrawRemainingEnergy(spriteBatch, this._displayedEnergy);
            }

            DrawScoreAndLivesRect(spriteBatch);
            DrawScore(spriteBatch, this._displayedScore);
            DrawLives(spriteBatch, livesLeft);

            if (isPaused)
            {
                DrawPausedMessage(spriteBatch);
            }

            spriteBatch.End();
        }
Exemple #5
0
        public override void Draw(GameTime gameTime)
        {
            if (this._transitionTexture == null)
            {
                return;
            }

            ISpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();
            spriteBatch.DrawTexture(this._transitionTexture, Vector2.Zero, null);
            spriteBatch.End();
        }
Exemple #6
0
        /// <summary>
        /// Draw everything in the WorldToLoad from background to foreground.
        /// </summary>
        public void Draw(GameTime gameTime, [NotNull] ISpriteBatch spriteBatch)
        {
            var windowPosition = this._worldWindow.WindowPosition;

            spriteBatch.WindowPosition = this._worldWindow.WindowPosition;
            var tileRectangle = GetRectangleEnclosingTilesThatAreCurrentlyInView(windowPosition);

            spriteBatch.Begin(this._applyEndOfWorldEffect ? this._endOfWorldEffect : null);
            WorldRenderer worldRenderer = new WorldRenderer(tileRectangle, spriteBatch, GlobalServices.SpriteLibrary);

            worldRenderer.RenderFloorTiles(ref this._tiles);
            worldRenderer.RenderWorld(gameTime);
            spriteBatch.End();
        }
Exemple #7
0
        public void Draw(ISpriteBatch spriteBatch)
        {
            Rect clippingRect = this.absoluteClippingRect;

            if (spriteBatch.TryIntersectViewport(ref clippingRect))
            {
                spriteBatch.Begin(clippingRect);

                foreach (ISpriteJob spriteJob in this.jobs)
                {
                    spriteJob.Draw(spriteBatch, this.absoluteOffset);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// When overridden in the derived class, handles drawing to the buffer.
        /// </summary>
        /// <param name="rt">The <see cref="RenderTarget"/> to draw to.</param>
        /// <param name="sb">The <see cref="ISpriteBatch"/> to use to draw to the <paramref name="rt"/>. The derived class
        /// is required to handle making Begin()/End() calls on it.</param>
        /// <param name="camera">The <see cref="ICamera2D"/> to use when drawing.</param>
        /// <returns>True if the drawing was successful; false if there were any errors while drawing.</returns>
        protected override bool HandleDrawBuffer(RenderTarget rt, ISpriteBatch sb, ICamera2D camera)
        {
            // Draw the lights
            sb.Begin(BlendMode.Add, camera);

            foreach (var light in this)
            {
                if (camera.InView(light))
                    light.Draw(sb);
            }

            sb.End();

            return true;
        }
Exemple #9
0
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            _batch.Begin();

            if (RenderGrid)
            {
                DrawGridLines();
            }

            // Draw selection rectangle
            if (SelectionBounds != Rectangle.Empty &&
                ((SelectionBounds.Width > 5 || SelectionBounds.Width < -5) && (SelectionBounds.Height > 5 || SelectionBounds.Height < -5)))
            {
                var selectionBounds = Utils.RenderableRectangle(SelectionBounds);

                _batch.Draw(BlankTexture, selectionBounds, new Color(100, 0, 0, 75));
                Utils.DrawBorder(_batch, BlankTexture, selectionBounds, 1, new Color(150, 0, 0, 175));
            }

            // Render border around selected game objects
            if (SelectedGameObjects != null && SelectedGameObjects.Length > 0)
            {
                foreach (var o in SelectedGameObjects)
                {
                    Vector2 objScreenPos  = _world.ActiveCamera.WorldToScreen(new Vector2(o.BoundsF.X, o.BoundsF.Y));
                    var     objScreenSize = new Vector2(o.BoundsF.Width * _world.ActiveCamera.InvZoom,
                                                        o.BoundsF.Height * _world.ActiveCamera.InvZoom);

                    Utils.DrawBorder(_batch, BlankTexture,
                                     new Rectangle((int)objScreenPos.X, (int)objScreenPos.Y, (int)objScreenSize.X,
                                                   (int)objScreenSize.Y), 2, Color.DarkRed);
                }
            }

            // Render region borders
            if (RenderRegionBorders)
            {
                foreach (var region in _world.ActiveCamera.World.Regions)
                {
                    region.DrawBorders(_batch, BlankTexture, _world.ActiveCamera);
                }
            }

            _batch.End();
        }
Exemple #10
0
        /// <summary>
        /// When overridden in the derived class, handles drawing to the buffer.
        /// </summary>
        /// <param name="rt">The <see cref="RenderTarget"/> to draw to.</param>
        /// <param name="sb">The <see cref="ISpriteBatch"/> to use to draw to the <paramref name="rt"/>. The derived class
        /// is required to handle making Begin()/End() calls on it.</param>
        /// <param name="camera">The <see cref="ICamera2D"/> to use when drawing.</param>
        /// <returns>True if the drawing was successful; false if there were any errors while drawing.</returns>
        protected override bool HandleDrawBuffer(RenderTarget rt, ISpriteBatch sb, ICamera2D camera)
        {
            // Draw the lights
            sb.Begin(BlendMode.Add, camera);

            foreach (var light in this)
            {
                if (camera.InView(light))
                {
                    light.Draw(sb);
                }
            }

            sb.End();

            return(true);
        }
Exemple #11
0
        /// <summary>
        /// When overridden in the derived class, handles drawing to the buffer.
        /// </summary>
        /// <param name="rt">The <see cref="RenderTarget"/> to draw to.</param>
        /// <param name="sb">The <see cref="ISpriteBatch"/> to use to draw to the <paramref name="rt"/>. The derived class
        /// is required to handle making Begin()/End() calls on it.</param>
        /// <param name="camera">The <see cref="ICamera2D"/> to use when drawing.</param>
        /// <returns>
        /// True if the drawing was successful; false if there were any errors while drawing.
        /// </returns>
        protected override bool HandleDrawBuffer(RenderTarget rt, ISpriteBatch sb, ICamera2D camera)
        {
            sb.Begin(BlendMode.Add, camera);

            try
            {
                // Sort through the effects, grabbing those in view, then ordering by their drawing priority
                foreach (var effect in this.Where(camera.InView).OrderBy(x => x.DrawPriority))
                {
                    try
                    {
                        // Draw the effect
                        effect.Draw(sb);
                    }
                    catch (Exception ex)
                    {
                        // A single effect failed
                        const string errmsg =
                            "Error while drawing IRefractionEffect `{0}` for RefractionManager `{1}`. Exception: {2}";
                        if (log.IsErrorEnabled)
                        {
                            log.ErrorFormat(errmsg, effect, this, ex);
                        }
                        Debug.Fail(string.Format(errmsg, effect, this, ex));
                    }
                }
            }
            catch (Exception ex)
            {
                // Failed somewhere other than effect.Draw(), causing the whole drawing to fail
                const string errmsg = "Error while drawing IRefractionEffects for RefractionManager `{0}`. Exception: {1}";
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat(errmsg, this, ex);
                }
                Debug.Fail(string.Format(errmsg, this, ex));
                return(false);
            }
            finally
            {
                sb.End();
            }

            return(true);
        }
Exemple #12
0
        /// <summary>
        /// Draws the loading screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // If we are the only active screen, that means all the previous screens
            // must have finished transitioning off. We check for this in the Draw
            // method, rather than in Update, because it isn't enough just for the
            // screens to be gone: in order for the transition to look good we must
            // have actually drawn a frame without them before we perform the load.
            if (ScreenState == ScreenState.Active && ScreenManager.Screens.Count() == 1)
            {
                this._otherScreensAreGone = true;
            }

            // The gameplay screen takes a while to load, so we display a loading
            // message while that is going on, but the menus load very quickly, and
            // it would look silly if we flashed this up for just a fraction of a
            // second while returning from the game to the menus. This parameter
            // tells us how long the loading is going to take, so we know whether
            // to bother drawing the message.
            if (this._loadingIsSlow)
            {
                ISpriteBatch spriteBatch = this.ScreenManager.SpriteBatch;
                SpriteFont   font        = ScreenManager.Font;

                const string message = "Loading...";

                Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
                int      y        = viewport.Height / 3;
                Color    color    = Color.White * TransitionAlpha;

                // Draw the text.
                spriteBatch.Begin();
                spriteBatch.DrawCentredString(font, message, y, color);

                if (this._loadingMessage != null)
                {
                    spriteBatch.DrawCentredString(font, this._loadingMessage, y + 75, color);
                }

                spriteBatch.End();
            }
        }
Exemple #13
0
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            _spriteBatch.Begin();

            _spriteBatch.Draw(_mainBackground, _mainBackgroundRect, Color.White);
            _background1.Draw(_spriteBatch);
            _background2.Draw(_spriteBatch);

            foreach (var enemy in _enemies)
            {
                enemy.Draw(gameTime);
            }

            _player.Draw(gameTime);

            _spriteBatch.End();

            base.Draw(gameTime);
        }
Exemple #14
0
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            _batch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, ActiveCamera.Matrix);

            World.Draw(gameTime, _batch, ActiveCamera);

            Player.Draw(_batch);

            // TODO: Store world objects in an array [,] of List<GameObject>
            if (FightersShield.Parent == null)
            {
                FightersShield.Draw(_batch);
            }
            if (FireShield.Parent == null)
            {
                FireShield.Draw(_batch);
            }

            _batch.End();
        }
Exemple #15
0
        public void Draw(ISpriteBatch spriteBatch)
        {
            Rect clippingRect = this.absoluteClippingRect;
            if (spriteBatch.TryIntersectViewport(ref clippingRect))
            {
                spriteBatch.Begin(clippingRect);

                foreach (ISpriteJob spriteJob in this.jobs)
                {
                    spriteJob.Draw(spriteBatch, this.absoluteOffset);
                }
            }
        }
Exemple #16
0
        // Draw one of the squares at a grid coordinate.
        void DrawQuarterCircle(ISpriteBatch spriteBatch, TextureContent content, Rectangle rect, Vector2 gridOrigin, int beat, Color color, float filledness, int depth)
        {
            // we prefer beats to start at upper left, but left to this logic, they start at lower left

            // position of this measure
            Vector2 position = gridOrigin + new Vector2(((beat / 4) % 4) * rect.Width, (beat / 16) * rect.Height);

            Vector2 offset;
            switch (beat % 4)
            {
                case 0: offset = new Vector2(1, 1); break;
                case 1: offset = new Vector2(0, 1); break;
                case 2: offset = new Vector2(0, 0); break;
                case 3: offset = new Vector2(1, 0); break;
                default: offset = Vector2.Zero; break; // NOTREACHED
            }
            position += offset * new Vector2(rect.Width, rect.Height);

            Rectangle destRect = new Rectangle(
                rect.Left + (int)position.X,
                rect.Top + (int)position.Y,
                rect.Width,
                rect.Height);

            Spam.Graphics.WriteLine(new string(' ', depth * 4 + 4) + Label + ": beat " + beat + ", filledness " + filledness + ", destRect " + destRect.ToString());

            // Use NonPremultiplied, as our sprite textures are not premultiplied
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);

            Vector2 origin = new Vector2(0);

            // always draw a hollow quarter circle
            spriteBatch.Draw(
                content.QuarterHollowCircle,
                destRect,
                null,
                color,
                (float)((beat % 4 + 2) * Math.PI / 2),
                origin,
                SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically,
                0);

            // now maybe draw a filled circle
            Vector4 v = color.ToVector4();
            v *= filledness;
            color = new Color(v);

            spriteBatch.Draw(
                content.QuarterFilledCircle,
                destRect,
                null,
                color,
                (float)((beat % 4 + 2) * Math.PI / 2),
                origin,
                SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically,
                0);

            spriteBatch.End();
        }
Exemple #17
0
 /// <summary>
 /// Handles setting up the <see cref="SpriteBatch"/> and drawing the <paramref name="map"/>. This is where
 /// all the actual drawing to the preview map is done.
 /// </summary>
 /// <param name="sb">The <see cref="ISpriteBatch"/> to use for drawing.</param>
 /// <param name="map">The <see cref="IDrawableMap"/> to draw.</param>
 protected virtual void DrawMap(ISpriteBatch sb, IDrawableMap map)
 {
     sb.Begin(BlendMode.Alpha, map.Camera);
     map.Draw(sb);
     sb.End();
 }
Exemple #18
0
        protected override void DoRender(
            Moment now,
            GraphicsDevice graphicsDevice,
            ISpriteBatch spriteBatch,
            TextureContent content,
            HolofunkView view,
            Transform parentTransform,
            int depth)
        {
            bool positionMirrored =
                SecondaryViewOption == SecondaryViewOption.PositionMirrored
                && view == HolofunkView.Secondary;

            Vector2 p0 = m_p0 + parentTransform.Translation;
            Vector2 p1 = m_p1 + parentTransform.Translation;

            if (positionMirrored) {
                p0 = new Vector2(spriteBatch.Viewport.X - p0.X, p0.Y);
                p1 = new Vector2(spriteBatch.Viewport.X - p1.X, p1.Y);
            }

            Vector2 diff = Vector2.Subtract(p1, p0);
            float angleRadians = (float)Math.Atan2(diff.Y, diff.X);
            float length = (float)Math.Sqrt(diff.X * diff.X + diff.Y * diff.Y) / 2;

            // Use NonPremultiplied, as our sprite textures are not premultiplied
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);

            spriteBatch.Draw(
                content.TinyDot,
                p0,
                null,
                Color,
                angleRadians,
                new Vector2(0f, 1f), // we pivot around the center of the left edge of the 2x2 square
                new Vector2(length, LocalTransform.Scale.Y),
                SpriteEffects.None,
                0);

            spriteBatch.End();
        }
Exemple #19
0
        public void Render(ISpriteBatch spriteBatch, V2 cameraPosition)
        {
            spriteBatch.Begin();

            for (int i = 0; i < positionedWorldCells.Length; i++)
            {
                if (positionedWorldCells[i] == null)
                    continue;

                for (int j = 0; j < positionedWorldCells[i].Count; j++)
                {
                    var cell = positionedWorldCells[i][j];

                    if (cell.Tile == null)
                        continue;

                    spriteBatch.Draw(cell.Tile.Texture,
                        new Rect(0, 0, TileWidth, TileHeight),
                        new Rect((int)cell.Position.X, (int)cell.Position.Y, TileWidth, TileHeight),
                        0f,
                        baseDepth - ((i * 100) + j) * HeightRowDepthMod);

                    spriteBatch.DrawString(SysCore.SystemFont, cell.Position.X + ", " + cell.Position.Y, new V2(cell.Position.X, cell.Position.Y), new V4(255), 0f, 1f, 1f);

                }
            }

            spriteBatch.End();
        }
Exemple #20
0
        protected override void DoRender(
            Moment now,
            GraphicsDevice graphicsDevice, 
            ISpriteBatch spriteBatch,
            TextureContent content,
            HolofunkView view,
            Transform parentTransform, 
            int depth)
        {
            Transform combinedTransform = parentTransform.CombineWith(LocalTransform);

            spriteBatch.Begin();

            Vector2 textSize = content.SpriteFont.MeasureString(m_text);
            Vector2 origin = Vector2.Zero;

            if (Alignment == Alignment.Centered) {
                origin = textSize / 2;
            }
            else if (Alignment == Alignment.TopRight) {
                origin = new Vector2(textSize.X, 0);
            }

            spriteBatch.DrawString(
                content.SpriteFont,
                m_text,
                combinedTransform.Translation,
                Color,
                Rotation,
                origin,
                combinedTransform.Scale.X,
                SpriteEffects.None,
                0);

            spriteBatch.End();
        }
Exemple #21
0
        /// <summary>
        /// When overridden in the derived class, handles drawing to the buffer.
        /// </summary>
        /// <param name="rt">The <see cref="RenderTarget"/> to draw to.</param>
        /// <param name="sb">The <see cref="ISpriteBatch"/> to use to draw to the <paramref name="rt"/>. The derived class
        /// is required to handle making Begin()/End() calls on it.</param>
        /// <param name="camera">The <see cref="ICamera2D"/> to use when drawing.</param>
        /// <returns>
        /// True if the drawing was successful; false if there were any errors while drawing.
        /// </returns>
        protected override bool HandleDrawBuffer(RenderTarget rt, ISpriteBatch sb, ICamera2D camera)
        {
            sb.Begin(BlendMode.Add, camera);

            try
            {
                // Sort through the effects, grabbing those in view, then ordering by their drawing priority
                foreach (var effect in this.Where(camera.InView).OrderBy(x => x.DrawPriority))
                {
                    try
                    {
                        // Draw the effect
                        effect.Draw(sb);
                    }
                    catch (Exception ex)
                    {
                        // A single effect failed
                        const string errmsg =
                            "Error while drawing IRefractionEffect `{0}` for RefractionManager `{1}`. Exception: {2}";
                        if (log.IsErrorEnabled)
                            log.ErrorFormat(errmsg, effect, this, ex);
                        Debug.Fail(string.Format(errmsg, effect, this, ex));
                    }
                }
            }
            catch (Exception ex)
            {
                // Failed somewhere other than effect.Draw(), causing the whole drawing to fail
                const string errmsg = "Error while drawing IRefractionEffects for RefractionManager `{0}`. Exception: {1}";
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, this, ex);
                Debug.Fail(string.Format(errmsg, this, ex));
                return false;
            }
            finally
            {
                sb.End();
            }

            return true;
        }
Exemple #22
0
        /// <summary>
        /// Begins drawing the graphical user interface, which is not affected by the camera.
        /// </summary>
        /// <param name="clearBuffer">When true, the buffer will be cleared before drawing. When false, the contents of the previous
        /// frame will remain in the buffer, only if the last draw was also to the GUI. When the last draw call was to the
        /// world, then this will have no affect. Useful for when you want to draw multiple GUI screens on top of one another.</param>
        /// <returns>
        /// The <see cref="ISpriteBatch"/> to use to draw the GUI, or null if an unexpected
        /// error was encountered when preparing the <see cref="ISpriteBatch"/>. When null, all drawing
        /// should be aborted completely instead of trying to draw with a different <see cref="ISpriteBatch"/>
        /// or manually recovering the error.
        /// </returns>
        /// <exception cref="InvalidOperationException"><see cref="IDrawingManager.State"/> is not equal to
        /// <see cref="DrawingManagerState.Idle"/>.</exception>
        public ISpriteBatch BeginDrawGUI(bool clearBuffer = true)
        {
            if (State != DrawingManagerState.Idle)
            {
                throw new InvalidOperationException("This method cannot be called while already busy drawing.");
            }

            try
            {
                // Ensure the RenderWindow is available
                if (!IsRenderWindowAvailable())
                {
                    if (log.IsInfoEnabled)
                    {
                        log.Info("Skipping BeginDrawGUI() call - the RenderWindow is not available.");
                    }
                    _state = DrawingManagerState.Idle;
                    return(null);
                }

                if (clearBuffer)
                {
                    // If the last draw was also to the GUI, clear the screen
                    if (!_lastDrawWasToWorld)
                    {
                        _rw.Clear(BackgroundColor);
                    }
                }

                _lastDrawWasToWorld = false;

                // Ensure the buffer is set up
                _buffer          = _rw.CreateBufferRenderTexture(_buffer);
                _sb.RenderTarget = _buffer;

                if (_buffer == null)
                {
                    return(null);
                }

                // Always clear the GUI with alpha = 0 since we will be copying it over the screen
                _buffer.Clear(_clearGUIBufferColor);

                // Start up the SpriteBatch
                _sb.Begin(BlendMode.Alpha);

                // Change the state
                _state = DrawingManagerState.DrawingGUI;
            }
            catch (AccessViolationException ex)
            {
                // More frequent and less concerning exception
                const string errmsg = "Failed to start drawing GUI on `{0}`. Device was probably lost. Exception: {1}";
                if (log.IsInfoEnabled)
                {
                    log.InfoFormat(errmsg, this, ex);
                }
                _state = DrawingManagerState.Idle;
                SafeEndSpriteBatch(_sb);
                return(null);
            }
            catch (Exception ex)
            {
                // Unexpected exception
                const string errmsg = "Failed to start drawing GUI on `{0}` due to unexpected exception. Exception: {1}";
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat(errmsg, this, ex);
                }
                Debug.Fail(string.Format(errmsg, this, ex));
                _state = DrawingManagerState.Idle;
                SafeEndSpriteBatch(_sb);
                return(null);
            }

            return(_sb);
        }
Exemple #23
0
        protected override void DoRender(
            Moment now,
            GraphicsDevice graphicsDevice, 
            ISpriteBatch spriteBatch,
            TextureContent content,
            HolofunkView view,
            Transform parentTransform,
            int depth)
        {
            // no texture = no-op
            if (m_texture == null) {
                return;
            }

            int left = -(int)((float)m_texture.Width * m_origin.X);
            int top = -(int)((float)m_texture.Height * m_origin.Y);
            Rectangle rect = new Rectangle(left, top, m_texture.Width, m_texture.Height);

            Transform combinedTransform = parentTransform.CombineWith(LocalTransform);

            Rectangle transformedRect = rect * combinedTransform;

            Spam.Graphics.WriteLine(new string(' ', depth * 4) + Label + ": parentTransform " + parentTransform + ", localTransform " + LocalTransform + ", combinedTransform " + combinedTransform + "; start rect " + rect.FormatToString() + "; transformedRect " + transformedRect.FormatToString());

            Texture2D texture = m_texture;
            SpriteEffects effects = SpriteEffects.None;

            if (view == HolofunkView.Secondary) {
                if ((SecondaryViewOption & SecondaryViewOption.TextureMirrored) != 0) {
                    effects = SpriteEffects.FlipHorizontally;
                }

                if ((SecondaryViewOption & SecondaryViewOption.PositionMirrored) != 0) {
                    // need to flip transformedRect around center of viewport
                    int newLeft = (int)spriteBatch.Viewport.X - transformedRect.Right;

                    transformedRect = new Rectangle(newLeft, transformedRect.Y, transformedRect.Width, transformedRect.Height);
                }

                if ((SecondaryViewOption & SecondaryViewOption.SecondTexture) != 0) {
                    HoloDebug.Assert(m_secondaryTexture != null);
                    texture = m_secondaryTexture;
                }
            }

            Color color = m_color;
            if (view == HolofunkView.Secondary && m_secondaryColor.HasValue) {
                color = m_secondaryColor.Value;
            }

            // Use NonPremultiplied, as our sprite textures are not premultiplied
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);

            spriteBatch.Draw(
                texture,
                transformedRect,
                null,
                color,
                0,
                m_origin,
                effects,
                0);

            spriteBatch.End();
        }