Is 2 lines of push/pop code for each pre-draw-state too many?
- by Griffin
I'm trying to simplify vector graphics management in XNA; currently by incorporating state preservation. 2X lines of push/pop code for X states feels like too many, and it just feels wrong to have 2 lines of code that look identical except for one being push() and the other being pop().
The goal is to eradicate this repetitiveness,and I hoped to do so by creating an interface in which a client can give class/struct refs in which he wants restored after the rendering calls.
Also note that many beginner-programmers will be using this, so forcing lambda expressions or other advanced C# features to be used in client code is not a good idea.
I attempted to accomplish my goal by using Daniel Earwicker's Ptr class:
    public class Ptr<T>
    {
        Func<T> getter;
        Action<T> setter;
        public Ptr(Func<T> g, Action<T> s)
        {
            getter = g;
            setter = s;
        }
        public T Deref
        {
            get { return getter(); }
            set { setter(value); }
        }
    }
an extension method:
        //doesn't work for structs since this is just syntatic sugar
        public static Ptr<T> GetPtr <T> (this T obj) {
            return new Ptr<T>( ()=> obj, v=> obj=v );
        }
and a Push Function:
        //returns a Pop Action for later calling
        public static Action Push <T> (ref T structure) where T: struct
        {
            T pushedValue = structure; //copies the struct data
            Ptr<T> p = structure.GetPtr();
            return new Action( ()=> {p.Deref = pushedValue;} );
        }
However this doesn't work as stated in the code.
How might I accomplish my goal?
Example of code to be refactored:
    protected override void RenderLocally (GraphicsDevice device)
    {
        if (!(bool)isCompiled) {Compile();}
        //TODO: make sure state settings don't implicitly delete any buffers/resources
        RasterizerState oldRasterState = device.RasterizerState;
        DepthFormat oldFormat = device.PresentationParameters.DepthStencilFormat;
        DepthStencilState oldBufferState = device.DepthStencilState;
        {
             //Rendering code 
        }
        device.RasterizerState = oldRasterState;
        device.DepthStencilState = oldBufferState;
        device.PresentationParameters.DepthStencilFormat = oldFormat;
    }