Customizing the Menu System

Feb 26, 2009 at 3:43 PM
I recently downloaded Ox and find the engine very well thought out.  I'm going to begin studying the source and attempting to make use of Ox for my game project.

I have a question off of the bat... I'm sure I'll have more later.  My question is: is it possible to customize the menu system?  I have some ideas for colors and fonts, and menu rectangles with rounded corners.  Would the engine code have to be modified?
Coordinator
Feb 26, 2009 at 9:07 PM
Hi Crichmon!

There are two ways to modify the game's GUI visuals without touching engine code, and an optional method to make the new visuals available from the Gui Editor -

1) The skinning way -

At your program's start up (or any other time you'd like to change your menus' visuals), grab the IGuiSkinGroups service from the engine's service container like so -

IGuiSkinGroups skinGroups = engine.GetService<IGuiSkinGroups>();

Then modify the property of each skin like so -

skinGroups.Whatever.TextureFileName = "WhateverTexture";

This is the easy way to modify the look of all the GUI components in your game. I'm not sure how much success you'll have getting rounded corners this way, though. If it doesn't work, you can try the second, more powerful way -

2) The IGuiViewFactory way -

Each GUI component uses a separate IGuiView strategy to implement its visuals. To completely change the appearance of all the GUI components, you must implement a new IGuiView class for each one. To see how this is done properly, look at the existing GuiView classes.

Further, each GUI component gets its concrete IGuiView instance from the IGuiViewFactory service. To change which IGuiView instance is handed out by the IGuiViewFactory service, you must create your own concrete IGuiViewFactory. To see how this is done properly, look at the existing GuiViewFactory class.

But further, the DefaultGameEngine forces you to use GuiViewFactory. This means you cannot use the DefaultGameEngine class if you want to use a different concrete IGuiViewFactory. Therefore you must make your own concrete engine class. This is actually pretty easy - feel free to copy and paste the DefaultGameEngine class as a starting point. The line that you would need to change is -

Services.Add<IGuiViewFactory>(new GuiViewFactory(this));
- to -
Services.Add<IGuiViewFactory>(new MyGuiViewFactory(this)); // assuming you named your view factory class "MyGuiViewFactory"

Optional) This will make things work how you want in your game. But, to make either tact work in the Gui Editor, you'll need to write a new IGamePlugin and change the Gui Editor's OxConsts.xml's <GamePluginFileName> to point to its .DLL and the <GamePluginTypeName> to your new, fully qualified concrete IGamePlugin class name. If you used the first approach, you will need to call the skin group alteration code from your game plug-in's CreateEngine() method.

Let me know if you have any more questions! :)
Feb 27, 2009 at 2:18 AM
Edited Feb 27, 2009 at 2:19 AM
Hi Bryan,

Ok, I attempted both solutions.  First the skinning method: the engine.Services.Get<IGuiSkinGroups>() function, does that returns a particular skinGroup that is shared across multiple components?  Perhaps I'm slightly unclear to the workings of the services.  So if I was modifying the GuiDemo project's Initialize method with

                IGuiSkinGroups skinGroups = engine.Services.Get<IGuiSkinGroups>();
                string textureName = "Ox/Textures/PlayerMarineDiffuse";
                skinGroups.RaisedSurface.TextureFileName = textureName;
                skinGroups.SunkenSurface.TextureFileName = textureName;

(and replace GuiComponents with two virtual keyboards)
then the background of the buttons and keyboards should reflect that of the texture, correct?  I've figured out how to change the color of the text, just not the background.

The more powerful solution is interesting, learning the codebase will take some time, however I'm up for the challenge.

Question regarding focus with GuiComponents.  In my modification of GuiDemo (with two virtual keyboards), either keyboard can be selected at program startup.  However, once one of the keyboards is interacted with, the other keyboard is not selectable.  If one of the keyboards is removed from the screen (via adding a call to Dispose for the OnCloseClicked event handler), then the other keyboard is selectable.  I believe this same behavior would be observed if there were multiple dialogs on the screen.  What would the method be to allow switching focus between multiple keyboards or dialogs?

The information document stresses the value of the component/subcomponent method for organizing game elements, along with Domains and Documents.  I'm still learning these.  If I were to want to represent a simple 2d grid map of cells (for placing game elements), do you have any initial recommendations on how to integrate such a map with the existing infrastructure?

My questions will probably be about minute details of the engine as I become familiar with it; any tid bits of wisdom are helpful.

thanks,
Chris
Coordinator
Feb 27, 2009 at 3:51 AM

Hi again!

Well, my long response post got destroyed by Codeplex because my internet connection dropped! Hooray Codeplex!!! The lesson here being never write huge swathes of text inside a web browser :)

/me cries a little....

Anyways, here's the summary version -

Virtual Keyboards and Buttons each use different SkinGroups for their backgrounds. Since buttons are pressed / unpressed, they use the Raised and SunkenSurface groups for their backgrounds. Since Virtual Keyboards (being a subclass of Dialog) have no such pressed / unpressed state, they use the NormalSurface group for their background.

The reason you can't navigate away from a Virtual Keyboard is because it's Modal by default. Set its Modal property to false and you can set focus in the normal ways :)

For the grid / cell set up you've got, I'm -

Oh crap, I just found myself typing a huge swathe of text into my web browser again... Excuse me while I copy and paste to Wordpad...

/plays intermission song....

Ok, back.

For the grid / cell set up you've got, I'm not sure what you're really wanting to do. Do you want to create a new editor for manipulating 2D scenes? If so, we'll have to go into greater detail. If you want to use the existing Scene Editor to place your cell items, you don't need a grid representation in your scene. You simply place your components whereever you like, optionally using the Snap: Position functionality to make sure they're all lined up just so.

Let me know :)

Coordinator
Feb 27, 2009 at 4:51 AM
Edited Feb 27, 2009 at 4:53 AM
Uh oh... You called them subcomponents... Only the old documentation called them subcomponents... the old documentation that was never supposed to ship... Apparently I shipped the wrong documentation with Ox...

#$%#%$@#%$@@$#!!!!

/me cries harder this time...

Sigh... I guess I'll be getting out a new build even sooner than I imagined...

Anyways, for future reference, there's no such concept as "subcomponents" in Ox. Subcomponents previously existed as a concept in Ox half-way between the previous build and the current one. Subcomponents were supposed to never see the light of day... They were renamed "elements" just before the current release. The documentation for this was supposed to reflect that, but something went wrong...

Oh well, I'll just post the new documentation as soon as I can :/

/me runs away crying like a wee lass...
Coordinator
Feb 27, 2009 at 5:04 AM
You know, on the other hand, I really do like the way it sounded when you called them subcomponents. It seemed a very natural thing to call them. Maybe I'll rename elements back to subcomponents after all...

What do you think is a better name for the concept?
Feb 27, 2009 at 6:15 AM

The design patterns book (GoF) calls them Composite(s).  Component is a good name.  If you want to use Subcomponent, maybe that could be the accessor on a component to the child components?  Don't change a name simply from my question posting, if you have a good reason, stick with it.

It occurred to me about the dialog skin having a different surface variable from the services get method of IGuiSkinGroup.  You mentioned there was different documentation, I'll look forward to reading at the next build.

The 2d grid idea is more along the lines of, well, there would be some design, but a lot of the content in a scene, I'd like to create that programmatically at run time, so I'm using a granularity of cubes.  Sounds wierd.  If you can imagine zelda, except the floor squares are cubes the player's character stands on, and the walls are cubes on top of floor.  Each cube would be of a certain material and therefore have certain textures at the top, bottom, and sides.

For the Gui components, I figured that I can write a different component view class, or add a new gui component and viewer, if I want to represent a gui component differently.  Regarding fonts, specifically monospaced fonts, the GuiSkinGroups class loads the font from a png file in the contents folder tree that has each character in a different part of the picture.  I have a font that I'd like to add, with each symbol in a separate 16x16 bmp file -- so might it be possible to write my own implementation for fonts that could load each individual character from individual bmp files (added to the content pipeline somewhere)?  

Coordinator
Feb 27, 2009 at 7:06 AM
I understand your idea of a cube "map" pretty well. I think the editor in Tenchu 2 did something along these lines. I think what you're going to need for this particular task is a custom editor. You can read up on what little info there is about creating your own editor from the overview, but I think it'd make a great deal of sense to look at the source and keep in close contact with me. Since your editor will be presumable 3D and have a lot of traits similar to Ox's out-of-box Scene Editor, you will need to use a lot of the code that is in-lined in the Scene Editor. Now, there is a plan for me to extract out this common code to an abstract class for everyone's easy reuse. Once this is done, it will be much easier for you to make your custom editor. It will be an indeterminate amount of time before I can make this happen though. So you could, for the time-being, consider copying and pasting the entirety of the Scene Editor project (gasp!) and modify it for your specific needs. While this is a pretty gruesome thing, it could work well as a holdover until I can get done with the fore-mentioned abstract class extraction.

If you want to create totally new GUI components to replace the current ones, you'd have to start editing the source. The main problem with this is that Ox isn't yet available from a source repository. Thus, when I drop a new release, you will have to hand-diff all of the changes to keep current. This will be extra nasty due to the fact that I break the API hard and often. The reason I don't have Ox under public source control is the sad fact that I use a half-speed phone modem and can't get a good enough connection to do commits reliably.

More in answers in a moment...
Coordinator
Feb 27, 2009 at 7:12 AM
Edited Feb 27, 2009 at 7:16 AM
For the font stuff, I'm pretty sure you could write a content processor that will do as you explain. All it needs to do is take a path to one of the character files and output them as a single bitmap with each character in the correct position. Seem like it should *just work*.
Coordinator
Feb 27, 2009 at 7:26 AM
Edited Feb 27, 2009 at 7:30 AM
On further thought, I might recommend against copying the Scene Editor project. I'm not really terribly sure that your custom editor will have a lot of similarities to the Scene Editor. Instead, I recommend that you wrap your head around the document and editor frameworks and come up with your own editor from scratch, using the Scene Editor's code as a reference (copying and pasting only the pieces that you need). This will be a less gruesome stop gap and may actually help you develop your editor faster.

EDIT: When I said "from scratch", I meant by creating classes the inherit from / utilitize functionality from the Ox.Editor project. You definitely don't want to develop your editor from scratch scratch!