Sign in to follow this  
MatsK

Depth sorting issues

Recommended Posts

I enabled SpriteSortMode.FrontToBack in my drawing callback:

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            Resolution.BeginDraw();

            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, null, null, 
                RasterizerState.CullCounterClockwise, null, Resolution.getTransformationMatrix());
            m_ScrManager.Draw();
            spriteBatch.End();

            //Reset device to defaults before rendering...
            GraphicsDevice.BlendState = BlendState.Opaque;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
            GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
            GraphicsDevice.Viewport = new Viewport(0, 0, GlobalSettings.Default.ScreenWidth, GlobalSettings.Default.ScreenHeight);
            GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 0.5f, 1);
            m_ScrManager.Draw3D();

            HitVM.Step();

            base.Draw(gameTime);
        }

Then, in my UIScreen.Draw method, I did:

        public virtual void Draw()
        {
            foreach (KeyValuePair<string, UIElement> KVP in m_Elements)
            {
                try
                {
                    if (KVP.Value is UIDialog || KVP.Value is WillWrightDiag)
                        KVP.Value.Draw(m_SBatch, UIElement.GetLayerDepth(LayerDepth.DialogLayer));
                    else if (KVP.Value is UIButton)
                        KVP.Value.Draw(m_SBatch, UIElement.GetLayerDepth(LayerDepth.ButtonLayer));
                    else if (KVP.Value is UIImage)
                        KVP.Value.Draw(m_SBatch, UIElement.GetLayerDepth(LayerDepth.ImageLayer));
                    else
                        KVP.Value.Draw(m_SBatch, UIElement.GetLayerDepth(LayerDepth.Default));
                }
                catch(Exception)
                {
                    continue;
                }
            }
        }

Here is UIElement.GetLayerDepth:

        /// <summary>
        /// Gets the value of the corresponding layer depth.
        /// </summary>
        /// <param name="Depth">The depth for which to retrieve a value.</param>
        /// <returns>The value of the specified depth.</returns>
        public static float GetLayerDepth(LayerDepth Depth)
        {
            switch(Depth)
            {
                case LayerDepth.Default:
                    return 0.0f;
                case LayerDepth.ImageLayer:
                    return 0.8f;
                case LayerDepth.ButtonLayer:
                    return 0.9f;
                case LayerDepth.DialogLayer:
                    return 0.10f;
                default:
                    return 0.0f;
            }
        }

Then in Credits.cs, I added the WillWrightDiag to my list of elements to be drawn by UIScreen.Elements, as such:

            m_WillWrightDiag = new WillWrightDiag(WillImage, this, new Vector2(100, 100));
            m_WillWrightDiag.IsDrawn = false;
            m_Elements.Add("WillWrightDiag", m_WillWrightDiag);

Here's how I draw a UIDialog:

        public override void Draw(SpriteBatch SBatch, float? LayerDepth)
        {
            float Depth;
            if (LayerDepth != null)
                Depth = (float)LayerDepth;
            else
                Depth = 0.10f;

            if (IsDrawn)
            {
                Image.DrawTextureTo(SBatch, null, Image.Slicer.TLeft, Image.Position + Vector2.Zero, Depth);
                Image.DrawTextureTo(SBatch, Image.Slicer.TCenter_Scale, Image.Slicer.TCenter, Image.Position + new Vector2(Image.Slicer.LeftPadding, 0), Depth);
                Image.DrawTextureTo(SBatch, null, Image.Slicer.TRight, Image.Position + new Vector2(Image.Slicer.Width - Image.Slicer.RightPadding, 0), Depth);

                Image.DrawTextureTo(SBatch, Image.Slicer.CLeft_Scale, Image.Slicer.CLeft, Image.Position + new Vector2(0, Image.Slicer.TopPadding), null);
                Image.DrawTextureTo(SBatch, Image.Slicer.CCenter_Scale, Image.Slicer.CCenter, Image.Position + new Vector2(Image.Slicer.LeftPadding, Image.Slicer.TopPadding), Depth);
                Image.DrawTextureTo(SBatch, Image.Slicer.CRight_Scale, Image.Slicer.CRight, Image.Position + new Vector2(Image.Slicer.Width - Image.Slicer.RightPadding, Image.Slicer.TopPadding), Depth);

                int BottomY = Image.Slicer.Height - Image.Slicer.BottomPadding;
                Image.DrawTextureTo(SBatch, null, Image.Slicer.BLeft, Image.Position + new Vector2(0, BottomY), null);
                Image.DrawTextureTo(SBatch, Image.Slicer.BCenter_Scale, Image.Slicer.BCenter, Image.Position + new Vector2(Image.Slicer.LeftPadding, BottomY), Depth);
                Image.DrawTextureTo(SBatch, null, Image.Slicer.BRight, Image.Position + new Vector2(Image.Slicer.Width - Image.Slicer.RightPadding, BottomY), Depth);

                if (m_HasExitBtn)
                {
                    m_CloseBtnBack.Draw(SBatch, null, Depth);
                    m_CloseButton.Draw(SBatch, Depth);
                }
            }
        }

And here's how I draw a WillWrightDiag, which inherits from UIDialog:

        public override void Draw(SpriteBatch SBatch, float? LayerDepth)
        {
            float Depth;
            if (LayerDepth != null)
                Depth = (float)LayerDepth;
            else
                Depth = 0.10f;

            if (IsDrawn)
                SBatch.Draw(m_WillWrightImg.Texture, m_WillWrightImg.Position, null, null, new Vector2(0.0f, 0.0f), 0.0f, null, 
                    Color.White, SpriteEffects.None, Depth);

            base.Draw(SBatch, LayerDepth);
        }

Despite this, I still get this weird case where the Maxis-button is drawn on top of the dialog and the exit button is occasionally not drawn.

Why? :\

 

[attachment=32955:tsocredits.png]

 

Is there a better, less error-prone way to achieve depth sorting?


Here is the entire code for Credits.cs if it helps:

using System;
using System.Timers;
using System.Collections.Generic;
using System.Text;
using Gonzo;
using Gonzo.Elements;
using Files.Manager;
using Files.IFF;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GonzoTest
{
    public class CreditsScreen : UIScreen
    {
        private UIImage BackgroundImg, TSOLogoImage, BackButtonIndentImage, WillImage;
        private UIButton MaxisButton;

        private Iff m_Credits;
        private List<string> m_CreditsStrings = new List<string>();
        private UIControl m_CreditsArea;
        private float m_CreditsY = 0;       //Upwards position of credits text.
        private float m_CreditsCenterX = 0; //Center of credits area.
        private Timer m_CreditsTimer;       //Timer for controlling text scroll.

        private WillWrightDiag m_WillWrightDiag;

        public CreditsScreen(ScreenManager Manager, SpriteBatch SBatch) : base(Manager, "Credits", SBatch, 
            new Vector2(0, 0), new Vector2(GlobalSettings.Default.ScreenWidth, GlobalSettings.Default.ScreenHeight), 
            GlobalSettings.Default.StartupPath + "\\" + "gamedata\\uiscripts\\credits.uis")
        {
            BackgroundImg = (UIImage)m_Elements["\"BackgroundImage\""];
            TSOLogoImage = m_Controls["\"TSOLogoImage\""].Image;
            BackButtonIndentImage = m_Controls["\"BackButtonIndentImage\""].Image;
            WillImage = (UIImage)m_Elements["\"WillImage\""];

            MaxisButton = (UIButton)m_Elements["\"MaxisButton\""];
            MaxisButton.OnButtonClicked += MaxisButton_OnButtonClicked;

            m_WillWrightDiag = new WillWrightDiag(WillImage, this, new Vector2(100, 100));
            m_WillWrightDiag.IsDrawn = false;
            m_Elements.Add("WillWrightDiag", m_WillWrightDiag);

            m_Credits = FileManager.GetIFF("credits.iff");
            m_CreditsArea = (UIControl)m_Controls["\"CreditsArea\""];
            m_CreditsY = m_CreditsArea.Size.Y;

            foreach(TranslatedString TStr in m_Credits.GetSTR(163).GetStringList(LanguageCodes.EngUS))
            {
                foreach (string Str in TStr.TranslatedStr.Split('\n'))
                    m_CreditsStrings.Add(Str);
            }

            m_CreditsTimer = new Timer(300);
            m_CreditsTimer.Elapsed += M_CreditsTimer_Elapsed;
            m_CreditsTimer.Start();
        }

        private void M_CreditsTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            m_CreditsY -= 1.5f;
        }

        private void MaxisButton_OnButtonClicked(UIButton ClickedButton)
        {
            m_WillWrightDiag.IsDrawn = true;
        }

        public override void Update(InputHelper Input)
        {
            m_WillWrightDiag.Update(Input);

            base.Update(Input);
        }

        public override void Draw()
        {
            BackgroundImg.Draw(m_SBatch, null, 0.0f);
            TSOLogoImage.Draw(m_SBatch, null, 0.0f);
            BackButtonIndentImage.Draw(m_SBatch, null, 0.0f);

            float Separation = 1.0f;

            foreach (string Str in m_CreditsStrings)
            {
                m_CreditsCenterX = (m_CreditsArea.Size.X / 2) - (Manager.Font12px.MeasureString(Str).X / 2);

                if ((m_CreditsY + Separation) > m_CreditsArea.Position.Y && (m_CreditsY + Separation) < m_CreditsArea.Size.Y)
                {
                    m_SBatch.DrawString(Manager.Font12px, Str, new Vector2(m_CreditsArea.Position.X + 
                        m_CreditsCenterX, m_CreditsY + Separation), Color.Wheat);
                }

                Separation += 15.0f;
            }

            base.Draw();
        }
    }
}

Also, why is the chat down? :\ There's a much higher signal to noise ratio in the chat.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this