Jemgine

  • entries
    22
  • comments
    7
  • views
    77959

Immediate Mode Gui

Sign in to follow this  
Deyja

2179 views

So I wanted a simple GUI library for XNA, but all the ones I found sucked. Let me preface this by saying that there are some very good gui libraries out there for XNA, if what you want is a set of traditional controls. I don't. Some of these libraries suck, some of them don't, but what they all have in common is their complexity and depth. This is not one of the cases where depth is good for me. I've built 'traditional' guis before, I even wrote a very large gui library in SDL. I called it gum (because gum is gooey, get it?) and used it for several things.

jileed.jpg

It had just about every control imaginable. So with that experience, I know that that is not the road I want to go down. Instead I want to explore a new fad called an Immediate Mode gui. That other kind, with it's hierarchy of controls, is called Retained Mode, because the state is retained in the controls. The controls are actually objects that continue to exist, and to change the gui, you manipulate this set of objects. The biggest difference in an Immediate Mode gui is that there are no controls.

Some of the advantages an Immediate Mode gui has over the other way of doing things are, in a large app with a complicated gui like a map editor or Word, nothing at all. For these big complicated maps, the Retained Mode methodology of using nested controls and event callbacks works very well and there's no need to shake things up. Immediate Mode guis do not scale well to more complex projects. They can't hide the complexity.

That's enough rambling about theory. There's plenty of that on the internet already. Most of the things that made the retained mode libraries I examined so complex no longer matter. I don't need fancy controls (I might only need buttons), I don't need floating windows that the user can drag and drop. I don't even need to be able to skin it, instead I just draw it. What's seriously lacking on the internet is implementations, and since I need so little, the implementation is simple, too.

I'm going to start with a simple main menu. It has a bunch of buttons on the left. Clicking a button changes the panel on the right (Opening the options screen, for example). I don't know how to present this besides dumping some code. So here is some code.


var Imgui = new Gui.Driver(prevMouseState, mouseState);
var BorderLayout = new Gui.BorderLayout(Graphics.Viewport.Bounds, 20);

Imgui.Button(BorderLayout.PositionItem(Gui.BorderLayout.Sides.West, 276), (A, B) =>
{
spriteBatch.DrawBorder(background, A, new Rectangle(33, 33, 190, 9), Color.White);

var Layout = new Gui.FlowLayout(A, 10);

Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => {
//Draw the button.
spriteBatch.Draw(buttonPlayAlone, C, D ? Color.Plum : Color.White); },
() => { /* Do Stuff if the button is clicked */ });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonHostOnline, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Host; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonJoinOnline, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Connect; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonOptions, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Options; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonQuit, C, D ? Color.Plum : Color.White); },
() => { Quit(); });

},
() => { });


I'm using XNA for rendering (obviously), and lots of lambdas. The result of this is

imgui.png

All of the types involved (FlowLayout, BorderLayout, Driver) operate independently. They can be used individually, but together they allow complex arrangements. Unique to my technique is, I believe, the lack of an 'item id'. It still exists, in a sense, in the form of the 'SelectedWindow', but instead of assigning an id to every item, I require the client code to deal with it when it's appropriate.

What I want to know is, what do you want to be able to do with an immediate mode gui? If you've reviewed the material available on the internet, what don't you understand about how they work?
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

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