Just returned from sunny Barcelona. Had a great time there, and I feel well rejuvenated and ready to continue coding again. In other news, I am writing this post from my university computer labs because my new student flat does not have an internet connection yet. This means I may not be online a lot in the next week but I will be able to get on with coding anyway. In terms of my progress I will first be concentrating on finishing up the code I made for polygonal / rectangle intersections for the imagemap. Sev commented that it would be useful to provide a standardised way for people to reuse this code so I will abstract the intersection stuff away from my imagemap-specific code. After that is done I will move on to the parser for the XML-based virtual keyboard info file. Thanks to Vincent / Tanoku the has developed a base XML parser that I can extend for my own needs. So I will first have to understand his code, tie down the exact format, then write my Parser class to parse the format. I’m very excited to finally be fully concentrating on the project. If my plans go without a hitch I think I should still be on track to have a good amount of code completed by the first evaluation.
Month: June 2008
Been a while since I’ve updated my blog, but rest assured my project work has been progressing well. I’ve made tremendous progress in terms of my understanding and ideas for the project, and have even made a substantial start on coding….finally!
Progression of ideas
Since my last post I have gone from understanding the general techniques that my virtual keyboard will utilise, to the details of the project. I have also discussed my progress with Eugene, and he helped me by further explaining his original ideas for the keyboard. Some of the key areas I have looked are discussed below.
Handling of images
Had to look into what code existed to load images. Found that the ImageManager class would do all the hard work, including the loading of images from within a zip archive. The ThemeModern class of the GUI helped me understand how I would use this.
Format of the keyboard’s ini file
I adopted Eugene’s original idea of extended the HTML imagemap format, to give a simple XML file that would encapsulate all the information needed to describe the different resolutions. For example:
<keyboard> <resolution=320xy> <mode=normal> <image="key_normal.bmp"> <map> ... </map> </mode> ... </resolution> ... </keyboard>
I will write a very simple, specialised XML parser for parsing this file, and the specific format of it will be tied down at a later date.
Polygon intersection methods
As I needed to allow for polygonal areas in the image map for the keyboard I had to research algorithms for determining whether a point is inside a polygon. This was known as the Point In Polygon problem. There were a number of different algorithms, but the one that seemed to be simple and quick was the ray casting method. This method works by testing how many times a ray starting from the point intersects the edges of the polygon. If this number is odd then the point is inside the polygon.
Idea of having hierarchy of image map areas
After looking into polygonal intersection routines, I thought that my virtual keyboard could run into efficiency issues when it tries to find out which area of a map was clicked, because there would be alot of different areas it could be. This lead me to think that I could arrange all the imagemap areas into a hierarchy based on areas of the keyboard. It would be similar to the Bounding Volume Hierarchy technique that I used when implementing a ray tracer for my Computer Graphics assignment. Whether this will be needed or not will remain to be seen, but the idea is there.
Started coding
I felt that now was a good time to start writing code. I started by:
- Writing the header file for the VirtualKeyboard class – defining its interface and key methods
- Writing support classes for the image map areas – including intersection method (that would detect whether a point was inside the area or not)
- Made a start on writing of simple XML parser for the ini file
I’m off on holiday tomorrow, so I won’t be around for a week. But once i’m back i’ll be able to really crack on with the coding.
After my initial research into the virtual keyboard implementation on the PSP port, I thought it was time to start working out how my generalised virtual keyboard would be implemented. This involved me looking further into ScummVM’s event management system, working out how the graphics would be displayed, and thinking about how it will all fit together.
Event Management
I had already discovered that each OSystem had a pollEvent() function that assigned the state of the system’s input device to an Event object. But I needed to extend my knowledge, working out how the game engine came into it. To do this I chose to look at the source code of the Scumm engine. In the main loop of the Scumm engine – ScummEngine::go() – two important things occurred on each iteration:
- waitForTimer() is called to limit scumm update
- the scummLoop() is called to update engine
waitForTimer() basically just pauses the thread for a specified time, but as user input may occur in this time it has to handle it. So:
- waitForTimer() calls parseEvents() every 10 ms.
- parseEvents() calls EventManager::pollEvent() in a loop until it returns false (ie. no more events)
- EventManager::pollEvent() just calls OSystem::pollEvent() and also adds record/playback functionality, as well as key repeat functionality
- for each event returned by the EventManager, parseEvents() sets up engine-specific input state variables
Then from within scummLoop(), processInput() is called. This function sets up the mouseAndKeyboardStat variable which is used by the Verbs part of the engine to execute scripts. So, as the EventManager already handles special input events it makes sense for this class to be responsible for feeding virtual keyboard events back to the game engine. I envisage the EventManager::pollEvent() method including code like this:
result = virtualKbd->pollEvent(event); if (!result) result = system->pollEvent(event);
Graphical display
In Eugene’s ideas for the virtual keyboard he had recommended that the virtual keyboard should live in the same 16-bit surface as the GUI. This made sense to me, as it should not be mixed up with the game graphics, but I did not really have a proper grasp of how the graphical layers of ScummVM were organised. Therefore I looked at the OSystem interface, and found out that graphics in ScummVM were implemented in three layers: game, overlay and mouse, and it was the backends job to draw these layers to its screen in that order. The OSystem interface provided a method for each of these layers that copies (or blits) a given bitmap into the layer. So for my virtual keyboard implementation I would have to call the OSystem::copyRectToOverlay() function in order to copy the keyboard’s bitmap into the overlay. If I were to implement some sort of roll-over or keypress effects then that would involve additional calls to this function to update the key concerned.
GUI loop
While investigating the way overlay graphics are done, I looked through a lot of the existing ScummVM GUI code. As well as looking at the graphics stuff, I also had a look at how the GUI main loop is carried out. This main loop basically allowed the GUI to process all the user input until all dialogs were closed. It made sense for my virtual keyboard to use a similar method as Eugene’s notes said that it was safe to assume the game engine would be paused when the keyboard was active. What this meant was that while the virtual keyboard was active it would process the mouse clicks, and build up a list of virtual key pressed events. Then once the virtual keyboard is inactive, it will deliver these events to the EventManager via its pollEvent() method (see the code fragment above).
Conclusions
My plans for the virtual keyboard are coming together well. The main concern I have at the moment is whether my assumption of having a separate virtual keyboard class is a good one. I have considered these other approaches:
- build functionality into base OSystem class – probably not a good idea because it may involve modifying existed back-end implementations.
- implement as a GUI dialog – makes sense in that its use will be very similar to a GUI dialog. However, probably not a good idea to tie it to the existing GUI implementation, especially as it will use its own configuration files. Although separate from GUI there is nothing stopping us making the keyboard look consistent with the GUI theme.
The obvious next step is to start thinking about the various initialisation files that the virtual keyboard will need, this will include:
- what extra information needs to be stored in the imagemap file?
- how will this imagemap file be parsed – using an xml library (e.g. TinyXML) or by writing my own specialised code?
- ini file – what information is needed in here?
If having rollover effects will be a good feature to include, I will also investigate some efficient way to do this.