Nick Darnell

So...in OpenGL I would use glOrtho(0,1,1,0,0,1) before processing my UI draw calls to set up my screen to be:

0,0 . . 0,1
.
.
1,0 . . 1,1

that way, I could tell a UI component to be at 0.1, and it would make it so at any aspect ratio, any resolution, that UI component would always draw 10% to the left of the side of the screen.

I want to do something similar to the UI system I'm working on for XNA, but I'm not sure how to setup the XNA camera to switch to an Orthographic projection before I process my UI components using the sprite batch.

Anybody know


Re: XNA Framework Orthographic UI

tportz

The SpriteBatch class automatically uses an orthographic projection, although its dimensions are in pixels, not percentage of the screen. You could, for example, multiply the viewport width by 0.1 to get the proper value in pixels. I don't see anything in the SpriteBatch class that would allow you to change the projection matrix. In C++ you could just call SetTransform on the device, but XNA doesn't have that functionality.



Re: XNA Framework Orthographic UI

Nick Darnell

Aye, I noticed that the spritebatch allows you to pass in the rectangle, which has to be integer values for everything. However, one of the overloads for spritebatch Draw allows you to pass in Vector2 for position, which is comprised of floats. I had hoped that would allow it to work off percentage but nope

I've been multiplying the width/height by the percentages for now, but it feels so...dirty.




Re: XNA Framework Orthographic UI

Ben Vanik

The easiest hack (with the relatively hardest one being rewriting SpriteBatch) is to subclass SpriteBatch and add the methods you want. I did something like this in one of my projects that had overloads for all the methods that did the math and passed the absolute values on. Kept my code a lot cleaner!



Re: XNA Framework Orthographic UI

Nick Darnell

well, this sucks. Thanks for making InternalDraw private in SpriteBatch MS

Turn that c.r.a.p. to protected so I can use my own structures like a rectangle comprised of floats. Without having to reinterpretate them to rectangles / vector2's.

Looks like I'm going the hardest route.




Re: XNA Framework Orthographic UI

KleMiX

don't you like Transformed vertices If no Matrix has a method CreateOrto or something like that...






Re: XNA Framework Orthographic UI

Bill Reiss

Ben Vanik wrote:
The easiest hack (with the relatively hardest one being rewriting SpriteBatch) is to subclass SpriteBatch and add the methods you want. I did something like this in one of my projects that had overloads for all the methods that did the math and passed the absolute values on. Kept my code a lot cleaner!

Yeah I did this too, made it easy to scale my sprites to any game surface resolution. You can see that code in Dr. Popper in the ScaledSpriteBatch class.






Re: XNA Framework Orthographic UI

Nick Darnell

I made some progress with my UI system as you can see below. Note the button in form two is actually a child control :-D Getting all the events to fire based on rectangles when each used the local space of the parent space was a pain to figure out. Everything is pixel perfect too, so if your button has a portion that isn't visible it wont receive events.

Normal:



Scaled:


Does anybody know any good books on UI design from the ground up though So far I think I'm going about it in a "correct" way, but I thought I might ask for a good read. The biggest issue currently is insuring that *needed* calculations and functionality in the parent classes of controls can't be corrupted when inherited, but to insure inherited controls get to "have a say" if needed. If you know what I mean.

Sort of like the pixel perfect testing. Where on a control where there is only a single texture as the background you just check it. But on a frame, you've got to check each border rectangle, and then the border texture...etc.




Re: XNA Framework Orthographic UI

Fluxtah

I think ASP.NET is a great resource for UI design, and also the HTML DOM is a great resource.

The ASP.NET control framework is an excellent example, even though its not geared toward DirectX graphics, its still an interesting implementation of control heirarchies.

I would generally design a control heirarchy in a similar fashion, as goes with Win Forms development, its the same kind of structure.

There is a lot to learn from these areas, although only the design concepts would apply to games development but of course the implementation would differ.

just an idea :)

To add to this, try to think of the implementation from the top down, the low level details do not matter as much as someone using the API, so imagine it already exists and you are an end user, for instance.

Create a Panel with a button in the middle:

Panel p = new Panel(500,500);
Button b = new Button("Hello World");
p.ChildElements.Add(b);

Screen mainScreen = new Screen();
mainScreen.ChildElements.Add(p);

I hope I am not teaching grandma how to suck eggs here but I am just sharing my idea of UI design!

At the most basic level I would have a class similar to this:

 
public abstract class UiElement
{
  List<UiElement> ChildElements;
  UiElement Parent;
  Initialize();
  Render();
}

These are very simple examples, but what I am trying portray is that a control heirarchy is important, and also a design that considers how it will be used by end users, thats why I always like to write software from the highest level of abstraction and leave the implementation details till last.





Re: XNA Framework Orthographic UI

Nick Darnell

Yup, that's currently the way it is modeled. What I could really use though is help with the events. Currently the problem is the scalar value.

I've managed to render everything correctly by implementing a rectangle/matrix stack on top of the sprite batch. So before each control draws child controls it pushes it's current scalar value, and rectangle. The scalar value is multiplied by the last final scalar to get the new final scalar, same with left/top...except added.

That results in the correct image rendered.

Problem is...

Say I've got a frame, and in it, borders. Now at the top left, the image is 20 pixels in height, so I tell the left border it needs to start drawing at x = 0, y = 20, and I store the rectangle.

Now, suppose on the MouseDown/MouseMove events I want to try and test if the mouse is on the left border, so what do I do I test to see if it is inside the border rectangle. I project the mouse point into the space of the rectangle. But it doesn't detect the click. Why

Because the whole UI system had its scale changed to 75% meaning that while rendered correctly. Because I told the left border to start drawing at y = 20 inside the frame, based on an unscaled top-left texture height, that if I click between 15px - 19px that it will find no rectangle matching that value, and thus, never detect I'm clicking the left border at those points. Because I'm only scaling the width/height, the positions remain unaffected by scalar changes

I know I could brute force it, but I can only imagine there has to be a elegant way to go about this so all the internal points, sizes...etc can exist in their own little world, and be completely ignorant of their parents scale, or their own scale, or their parents parents scale...etc.

If anybody happens to know a good solution to this...




Re: XNA Framework Orthographic UI

Jonas Beckeman

I'm not sure how your system works, but if you use 2D matrices to describe scaling, position and rotation for sprites, then you can use simple matrix operations (cascading through the sprite hierarchy) to calculate the position of a point in a sprite coordinate space to the root/screen (or any other sprite) and vice versa.



Re: XNA Framework Orthographic UI

Fluxtah

Im not quite sure if I am understanding the problem correctly but can you not scale the mouse click vector before you test for a hit



Re: XNA Framework Orthographic UI

Nick Darnell

Yeah I can. I was just hoping to keep the mouse units constant. That way people don't really need to know that the mouse press came at 10,10 based on some scale. instead the mouse would always come in at the abs units - the left placement of all parent windows. Then some how in way hidden from the user there were a simple set of functions they could use, like getPointToScreen, getPointToClient, to learn any other info. I think I've got it working, I was on the right track before, I just had some other code I wrote screwing stuff up.

The hope is that scale is a non-issue, that's really what I'm shooting for. That way the user never needs to really care what scale he is at. Then again, if I don't scale the mouse units for the local system, the user would need to, to do surface tests on textures for collision.

Would it make more sense in the mouse event object to pass in the abs screen coords, and the local screen cords