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;
}