Tuesday, May 24, 2005

A Fully Functional DirectX C# GUI



Well getting there anyway. Currently it has a pretty good framework and it has Windows, Labels and Buttons. You can do cool stuff like:


Button button = new Button(device);
button.render += new renderHandler(OnRender);
}

public void OnRender(object sender)
{
   MessaeBox.Show("Button Has Been Pressed! :o");
}


Pretty swish! There are also delegates for moving over the buttons and stuff like that. I don't know how much of it I'll need but it's actually pretty modular so it's a nice tool. With it I'll begin the start menu stuff and game loading saving stuff all in a nice gui. I'll also develop the console so it fits into the GUI world :D. Take that Microsoft Framework ( (;_;) I wish I had your IME language support though))

Of course you may be thinking - that screen shot makes absolutely no sense. And you'd be right - it's the code behind it that's cool. Basically the character is window and he can be dragged around. I added some delegates to the window so the the text at the bottom of the screen changes depending on context of the mouse position. As I'm illterate you can see these messages make no sense :D The goal is to get a decent looking menu system in by Friday. (Provided I don't get interrupted at school too much and told to actually teach kids and do my job. There are midterms coming up so I don't think it will prove a problem :D)

Saturday, May 21, 2005

On Dragging and Dropping . . .

I like to play with lots of things at once - and one is a tool to easily manage my textures. Now the first thing I desired was drag and drop functionality. I found this to be a little tricky, I couldn't find too much documentation that helped but with a little experimenting here is what I got. This particular example is for loading PNG but could be trivially modified to support GIF, JPG and BMP - possible others too (whatever the windows Bitmap format supports)

The Plan

I want to drag images to my program and have them displayed. If it's anything other than .png nothing's displayed and the users cursor goes to the "no entry" sign.

To use drag and drop for a task such as this there are a few things that matter.

AllowDrop this should be set to true. I think it's present on any component so if you wish to add drag&drop to a button or some little icon or a picture box or . . . whatever - it's no problem! The important thing is you set it to true.

Next the Events - we only care about 2.

DragOver this is when you've dragged something and you're moving it over your control. Here you should report to the user - if it is something acceptable or not acceptable. (The cursor has the no-entry sign for NO! or it has a little box for YES!)

DragDrop we've let go in the control area so now do something magic with the thing we've dropped.

The Simplest Program Possible

Start a new windows project.



Now hop to the form designer.



Select a picture box and drag it on to the form. Go to the picture box properties section and under docking select Fill.



Okay a nice big grey box. Just what we've always wanted. We want to get some drag drop action going so let's set the AllowDrop bool. Now - I couldn't find this in the properties form-designer explorer! Maybe in later versions of VS.net it's there. So I added it manually into the VS.net pregenerated code.


private void InitializeComponent()
{

//A lot of windows generated code
...

        //
// pictureBox1
//
this.pictureBox1.AllowDrop = true;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(3, 16);
this.pictureBox1.Name = "pictureBox1";

...


With that added we'll now potentially be able to accept stuff dragged over to our form (well picture box specifically but it does take all the form-real-estate!). Next to events. So for this let's hop back to the form designer.



Click on the little lightening arrow for events and double click the space next to DragOver. This will take us into the programming section.

Programming OnDragOver


private void [Your Project Name]_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{




In this function we check what's being dragged in and whether or not we like it. Then we tell the computer our general feelings. So we want to check several things.

  1. Is it a file from windows-explorer (not the webbrowser :P, the file manager)?

  2. Does it have a file path associated with it?

  3. Does it use the .png extension?

  4. Will windows allow us to copy it?



We find this all out using DragEventArgs e this contain lots of useful stuff. There's a GetFormats method that allows us to check if the data being dragged can be converted into what we want. This function is obviously poorly named - it should be IsFormat. Because that's what it's used for. IsFormat(bitmap) for instance. But for an unknown reason it's called GetFormats.

So with this we'll check two things. If it's coming from Windows - this is pretty easy and we use one of preset formats, the second if it can be converted to file name. This is a little harder, I only discovered this format name by trial and error - though I'm sure it's documented somewhere. Enough chat let's see the code.


//Are we dragging a file in
if( e.Data.GetDataPresent(DataFormats.FileDrop) &&
e.Data.GetDataPresent("FileNameW"))
{




So we ask Is it from Windows? and CanWeGetAFileName from it. The W at the end of FileName might be for Windows I don't really know. You'd imagine the filename would just be a string but confusingly it's an array of strings! At position 0 though is the final name. I didn't check the other positions so who knows what mysteries they might hold.

The next thing to check are: Is it a PNG and Can we make a copy of it?. Not too hard!


if((e.AllowedEffect & DragDropEffects.Copy) != 0)
{
string[] filePathInfo = (string[]) e.Data.GetData("FileNameW", true);

if(filePathInfo.Length == 0)
return;

if(filePathInfo[0].ToLower().EndsWith(".png"))
{
e.Effect = DragDropEffects.Copy;
}
}





So the first IF statement is querying the dataobject and asking if it's okay to copy it. Does it contain the DragDropEffects.Copy flag? The we convert the data that's being dragged into an array of strings. We check the string array isn't empty and then take the first string of the array - which should be the file path. The final check is does it end with .png? - if it does, well then we're cooking.

Finally - the final line, where we're giving the go ahead for copying!


e.Effect = DragDropEffects.Copy;


We send back what we want to do with the thing be dragged. In our case we'll be copying it (rather than say moving it). Setting this changes the mouse cursor to something appropiate. That's our entire moving over function - cool heh!

Drag Drop

So the next and last event is when the user actually releases what's being dragged in the correct place. Then we want to load whatevers dragged up into the picture box. Pop back to the form designer, go to Events using the lightening bolt icon. Then scroll down to DragDrop. Double click the empty box next to it and wait to be transported to the code with the correct skeleton in place.

I'm going to throw down the code all at once. Because it's not complicated!


private void pictureBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string[] filePathInfo = (string[]) e.Data.GetData("FileNameW", true);
Bitmap bitmap =
new Bitmap(filePathInfo[0]);
this.pictureBox1.Image = bitmap;
}



And that's all there is to it. Drag and drop to your hearts content.



Post Scriptum

I know why it's an array of strings now! Well actually this is a guess but I assume it's if you grab a load of images than drag and drop them. This is very worth supporting too.

Wednesday, May 18, 2005

I have taken apart the toaster . . .

and now I sit on the kitchen floor surrounded by unidenfiable parts and wondering if I'll ever eat toast again. This sums up the current state of my project really. I'm putting it back together in a much cleaner fashion though. I'm in no hurry with my project and I think this is an important point, I have time for such luxurious fiddling, I have all the time I want. An detail to keep in mind with a hobby project or you might get burnt out.

As I go I notice small bugs that would cause havoc later on and be really quite hard to spot. I've actually worked on getting myself organized too so I have a todo list and a method. I don't think there's any point in posting about my method until I proven to myself that it works (and then it will only be that is works for me). I am still wrestling with a GUI system and I've decided something small and hard coded really isn't going to cut it - I need something reusable and quite seperate from my project.

So first question is - has some one else done this for me? Well microsoft has - they have the framework - which to me is a big rusty cage of cogs and springs in pot of green bubbling slime - it's all voodoo (I have little practice reading others code, it's something I need to work on) with little documentation. I guess it's easy to use but you don't know why you're doing things a certain way. If you don't know why you are doing certain things bugs are always going to seem extra intimidating. Their GUI system on the face of it looks very nice and all the source code is there (so you can work out why if you're determine - but for reading code I prefer printed and alas no printer). So I may steal bits of it once I have the foundation of my own system up and running. As I'm not using the framework then that's the frameworks GUI pretty much out.

Well second there's a book called "DirectX 9.0 User Interface Design and Implementation". It's not an awful book but it's not good - it could have been at least half the size for one thing. It really does waffle on at the start about things that anyone buying this book will almost certainly know - who starts learning DirectX by creating their own User Interface Library - no one! It would probably sell more by reducing the price and size. The descriptions of the actual code are pretty brief too, he doesn't describe what everything is going to be used for. This, of course, is no problem to look up as you write but surely the books purpose is to explain this kind of stuff. He doesn't give a reason why his design is this way, why not to do it another way - that's really what the book should have had to make it good or even excellent. At the moment it's more like a code repository. The following quote really sums it up for me:

Nowadays, in a world of skinnable apps like media players and
instant messengers, users can customize the look of their controls such
that they are non-rectangular. This can be implemented in Direct3D
by using alpha tested textures. However, this is an advanced topic that
is beyond the scope of this book.


Surely this is the exact scope of this book. Everything and everything about DirectX GUI's is what should be covered especially using alpha blending as it's it so basic. And we all want to use non-rectangle controls in a computer game!

Despite this the code seems to work and probably works very well. It's written in C++ but I assume most C#er's aren't going to find this a problem as they've probably programmed in this too and conversion is a snip (infact the code I've written looks a lot cleaner but I think that's just an intrinsic advantage C# has over C++ which tries to straddle both worlds of OOP and C-procedural). If you're looking for a GUI solution, at this point in time, it's defintely worth a look. There are also a number of articles over at GameDev but I didn't find the design philosphy to be my sort of thing at all. Still worth checking though!


Tags:

Sunday, May 15, 2005

Videos

This is well worth checking out. It shows a presentation by Peter Molyneux from Lionhead Studios talking about next generation games. It shows the movie which looks very impressive and also Black and White Two and a really cool "The Room" tech demo.

It's requires free registration - gah. A method I like to use to bypass time wasting is to use Firefox with the BugMeNot extension. That will get you through "free registration to view" very quickly.

I'm slowly reassembling my game today and working on supporting tools. All quite mundane stuff.

Monday, May 09, 2005

Game Loop and DXUT Framework

There's an interesting post over on Tom Miller's blog about the final words on game loop in C#. You may not know but the way shown in my tutorials uses the (once) standard method that causes some superflous objects to be created and destroyed each frame. Obviously we don't want that. But we don't want something really overly complicated either. Any there have been various different ways of doing a fast C# loop but generally they're not very pretty. This one isn't exactly elegance in a dress but it's worth a look, and supposedly will be the last word on the subject too!

Speaking of which that current "framework" thats suppose to help people get started is crazy! It seems far too complicated with far too much voodoo going on! A new programmer wants to be in his own little kingdom where he knows what every line does. The docs are rather sparse as well. It's not a framework I'll be using in the near future.

So last week in Japan was goldenweek, a week of bank holidays. I got nothing done :D

I've implemented the Game Loop mentioned in the blog. I couldn't find any "WindowMessage" data type anywhere in C# so with a little bit of googling I changed it to an Int32 and this doesn't seemed to have caused any problems. Also remember to add using System.Runtime.InteropServices;. I also didn't create a native methods class. That's about it though really, everything else is cool.