Saturday, February 26, 2005

Saturday 26th

Only managed a brief coding session today, and started off by tweaking the menus (yet again) to cope with the impending arrival of the Map Properties routine, which will allow the maps sizes to be changed dynamically at any point (as opposed to being fixed at runtime, as they currently are).

As I've now decided to handle the Map Properties system a little differently than I'd initially planned, the Tileset loading/refresh routines needed a new home, as did options to save/load Meta data and Mask data, so creating a Tile menu seemed to be the obvious choice.

I also took a little time out to have a look-see at the toolbar, just to see if there was space to add any more functions to it. I have space for about 14 more icons, which seems a lot until you consider that I have about 30 options I want to include! After careful examination, I concluded that the toolbar should house only important functions (loading, saving, and drawing tools), with secondary functions confined to the Menus.

While I was tinkering with the Toolbar, I came upon an idea to add bookmarks - essentially, you can hit a key to save your current position on the map; hitting the recall key returns you to the correct position, and even remembers which map you were editing at the time.

Although this took mere minutes to add, a keyboard conflict arose: I was using Alt+F9-F12 to store a bookmark, and F9-F12 to recall. However, F10 is a special key, and returns a different code to those of the other F-keys. Unable to find a decent solution to this, the bookmark code remains unused for the moment. On the plus side, I did work out how to manually "select" a tabber from within the program, so now my map select keys (F1 to F8, for those with a key fetish) now finally work as I originally intended. :)

The final task for the night was a brief tinker with the Map Properties code; currently this triggers a small window, into which you type the new dimensions for the map, but there were a few minor bugs which needed to be rectified first (this merely involved freeing up gadgets when the window was closed and returning the correct values). With the window now working properly, this will hopefully allow me to crack on with the more important code tomorrow.

Friday, February 25, 2005

Friday 25th

After yesterday's successes, I decided to continue plucking tasks from my To-Do list. First on the agenda was a keypress to prevent tile zero being plotted when the user draws with a brush. Essentially, tile zero is transparent in every tileset, and usually shows up as black (because the background is black).

Whenever a Brush is drawn, if there are any instances of tile zero, these get plotted too, overwriting anything that might be underneath. However, there may be instances where you need to draw a non-rectangular shape onto an existing map without plotting tile 0 - and thanks to a tiny bit of fiddling, the user can now hold Control when plotting a Brush to do just that (essentially this gives you a genuine transparency on tile 0).

This idea may be expanded to apply the current mask to the plotting procedure (currently the mask prevents certain tiles being drawn over - this could be tweaked to prevent masked tiles actually being plotted), but this will be logged on the Wish-List for now.

The next task of the day saw me implementing the Merge Visible routine, which takes all of the currently visible layers and merges them to the layer currently being edited (tile zero is not plotted, allowing the maps at the back to show through the gaps in the maps at the front). This routine took a while due to an interesting problem with Bank sizes (i.e. I was using the actual Bank size in bytes as opposed to the relative Bank size in doublewords).

That done, I finished up by adding a Swap Visible routine, which will - surprisingly - swap the two layers which are currently visible. This again took a little bit of thought, as I needed to add error handling should the user have too few/too many layers selected.

Thursday, February 24, 2005

Thursday 24th

Tackled the remainder of the Brush I/O code today, which involves saving the entire collection of brush buffers (as well as the Brush currently being used, the user can store up to 8 Brushes in temporary buffers and thus have a 'library' of commonly-used Brushes).

As has been the case all week, however, I struggled with this code making tweak after tweak; the problem with I/O is knowing what's going wrong - if you save a file and it won't load back in, has the save routine messed up or the load routine? The only way to work through the issues is edit the routines side by side to ensure that everything is read/written in the correct order.

With progress slow, I decided to turn my attention to my To-Do list, rather than waste valuable time pouring over what could turn out to be a very simple problem (I'm hoping a fresh look at the code tomorrow will yield some results).

* * *

The biggest remaining task on my list - something I'd been dreading for some time - was the Tileset integration. Currently, the code already contains commands that load in a default set of tiles when the program is run. While this is obviously fine for me - I merely tweak a line of code to use an alternative Tileset - it limits the Editor's functionality for anyone else wishing to create maps.

After careful tinkering, the user can now load in a Tileset to any one of the eight "slots" designated for Tilesets. As an added bonus, the program even handles Tilesets that aren't in the correct format; although the results are clearly bad, the program doesn't crash, which means that I don't have to write a lengthy routine to validate each file. As a final tweak, I added a refresh facility so that the tiles can be tweaked simultaneously in another package and 're-loaded' with a single click.

The next task was an idea that only occurred to me yesterday: the user can currently dump the screen or the entire Map to a BMP file - so why not the current Brush? A quick amendment to the Brush routine, and this was in and working beautifully. Far too many Editors overlook the facility to save graphics out from the editor, but in my experience this has been invaluable for the artist creating the tiles - it's easier to track down mistakes, and they can even tweak the tiles on the screen dump then slice this up into tiles again and re-import them.

Still in Brush territory, I expanded the Exchange Tile code to encompass Brushes as well (if you recall, the user can highlight a Tile with the Left button, then the replacement Tile with the Right button, then press a key to exchange all instances of the Left tile with the Right). It seemed a natural evolution to apply this to Brushes, since it now allows you to perform 'localised' tile exchanges.

Flushed with my progress, I also tackled another pretty big routine that displays a Static backdrop behind the map window. Though this probably isn't something I'll be using for Citadel, it will come in handy for other projects, especially those that utilise a static or parallax backdrop. The basic routine was up and running fairly quickly, but may need further refinement as things progress.

The final job for the night came as a result of adding the Static backdrop code: originally, when the Editor was first put into its GUI, one of the Layers had been reserved specifically for the Static backdrop. As this has now changed slightly (and given that I want to avoid restricting what sort of data a Layer can hold), I made the Static backdrop independent of the actual Layers, and expanded the number of Layers from six to eight.

Wednesday, February 23, 2005

Wednesday 23rd

After a couple of day's break from coding, I returned to the Editor to tackle an extremely quirky problem that had plagued Monday night's coding session; I'd put in the code required to Load and Save the current Brush, but for some reason the Load code wasn't functioning correctly.

I examined my code, made a few more tweaks, but the problem still persisted: if I grabbed a Brush then saved it, I couldn't load the Brush back in during that session - I physically had to quit the editor then restart it, at which point the Brush would load in. This pointed to a problem with the save routine, so I included a CloseFile command - but to no avail.

Tonight, as is typical with stubborn bugs, I solved the problem in about 30 seconds - the CloseFile command has to be applied to the variable used to read/write the data, and not by using the filename (as I had been doing). This tweaked, everything was working beautifully, and you can now quick-save a Brush and load it back in with ease.

The final task of the night was to fix a small bug in the Mini-Map routine I worked on in January; this was never completely finished, due to the fact that I wanted to tweak a couple of things after I implement the facility to change the map size. The bug was a quick fix, however, and merely needed to check and adjust a couple of display variables if the map was below a certain size.

Sunday, February 20, 2005

Sunday 20th

Another annoyingly slow start to the day saw me tinkering with drawing "constraints". It's almost standard these days for art packages to include a constraint option - often associated with the Shift key - which restricts the current drawing tool. For instance, in PhotoShop, holding Shift will ensure that the lasso tool draws perfect squares instead of rectangles, or that the line tool will draw perfectly horizontal, vertical, or diagonal lines.

I'd tinkered with this briefly a couple of months ago, but it was pushed to the bottom of my To Do list in favour of more important tasks. It is something I think is important to the toolset, however, and can envisage a number of scenarios for Citadel where it'll be, like, essential.

With things progressing slowly, I shifted my attention momentarily to another idea I'd had: displaying the dimensions of the shape currently being drawn (which struck me as an obvious omission as soon as I'd thought of it). This wasn't too painful to implement, partly because the variables exited anyway, and partly because my drawing routines all use a similar structure, but nevertheless will be worth its weight in gold.

Saturday, February 19, 2005

Saturday 19th

A brief stint with the Undo/Redo routine saw me cursing and swearing at the PC for a good hour, before deciding to work on something more productive. The first task was to implement the option to lock a particular layer to prevent it being edited or drawn on accidentally, and was a fairly simple addition. I also included the option to lock / unlock all layers (yes, I can't envisage a scenario where you'd want to lock every layer either, but you might want to lock every layer apart from one - in which case you'd lock all layers then unlock the desired layer). Saves on shoe leather, if nothing else. :)

The second job was to implement the Clear option, allowing you to clear the current layer with the tile currently selected with the Left button. As an extension of this, I also added the Clear All option (though this may require the addition of a prompt to prevent accidental erasure).

To round things off, and given that I was updating the Layer menu quite extensively, I introduced a Copy / Paste layer facility for maximum editing flexibility. This routine took a while to debug as the keypress would hardly ever register; it dawned on me that clicking the checkbox to turn a layer on/off actually takes the focus away from the main window - thus, when the Paste key is hit, the program is trying to manipulate the checkbox instead of the main window. This is a personal bugbear of mine, so a visit to the Blitz forums might be on the cards.

The final task of the night involved making a start on the documentation; with the Menus filling up with options and the number of free keys rapidly diminishing, I need to make a start on the documentation before I forget about the myriad features that have been included along the way. I don't have time to learn how the Help file should be properly created, however, so for the moment I'm using good (?) old Microsoft Word.

Friday, February 18, 2005

Friday 18th

Today saw me tackling the Undo / Redo routine head-on, but didn't manage to get much done due to being chronically tired. I started off by putting in the basic code to store and recall a buffer, then added the key presses to activate these. However, there was still a slight problem with the Redo part of the routine.

After a great deal of head scratching - which involved me simultaneously stepping through the code on-screen and on paper - it suddenly dawned on me why the routine wasn't working: when an action is performed, the map is saved to a buffer before the program draws to it. This is fine for the Undo, because you simply recall the saved buffer. However, should you then try to Redo what you just did, the results are quirky because there is no buffer to recall.

Therefore, whenever an action is performed the program needs to save both the map before the edit (for the Undo) and the map after the edit (for the Redo). Hopefully I can crack the routine tomorrow. :)

Thursday, February 17, 2005

Thursday 17th

The first task of the day was to track down a couple of bugs in yesterday's Brush masking code; for some reason, I'd neglected to implement the code properly, so unexpected problems occurred when the handling point of the Brush was toggled (if you recall, the Brush can be handled - like Brushes in Dpaint - from the top-left or the bottom-right, according to user preference).

Additionally, I also needed to tweak the clipping routine; when a Brush goes off the edge of the screen, Blitz automatically clips the image for me; in mask mode, however, the program reads the information underneath the brush before plotting it, so when the Brush goes off screen, erroneous data gets thrown into the mix and things start to go a little bit bonkers.

The next tweak on my list was to sort out the Tile window and specifically, choosing tiles with the +/- keys; although this is possibly a little redundant now (a throwback to the time when the tiles were displayed in a continuous strip across the bottom of the screen), it still has its uses. The problem was to get the cursor moving properly within the Tile window, but took just a few minutes.

The biggest task of the day was to start on the Undo / Redo routines; I've been putting these off for far too long, but the Editor has reached the point where they really do need to be added (I've lost count of the times I've screwed up my test map and had to reload it).

The routine, in theory, is reasonably simple: you hold a number of buffers in memory, each the size of the current map. When a change is made, you stash the contents of the map into a buffer, and if the Undo is activated, you copy this buffer back over to the map. With this in mind, I spent a little while writing a nice, modular routine to copy data from Bank to Bank. - and that was when I discovered Blitz's rather handy CopyBank command... D'oh!

I rounded off the day by adding a little Splash Screen when the program starts but, like all artistic endeavours, it took longer to draw the image than it did to implement the code. :)

Wednesday, February 16, 2005

Wednesday 16th

After another sizeable delay in the proceedings, I started tinkering with the Editor again; following a discussion with another programmer at the weekend, it seems clear that the Editor - affectionately labelled FishEd - is suitable for their current project too, so I now have the motivation I need to get the program to Beta stage before the end of February.

I have a huge number of tasks on my To Do list, which also includes a number of tweaks and bug fixes; the problem with a project such as this is that ideas rapidly spawn other ideas, but shooting off at tangents often results in code seeming finished, but not actually being so.

However, such tasks are useful in a way, as I can always use them to get acquainted with the editor again, limber up at the start of a coding session, or tackle something quickly when I want to code but don't have much time.

A good example of this is the Left/Right button functionality: in Pen mode, the user can assign a tile to the Left and Right mouse buttons, allowing them to paint using two different tiles without constantly having to move back to the Tile Selector. However, the Left/Right functionality had only been implemented in Pen mode, so this morning's job involved applying this functionality to all of the other drawing tools.

A huge chunk of time was spent sorting out the menu code again (specifically, getting the program to perform an appropriate action for each menu item). It's not the most enthralling work, but all of the menus - with the exception of routines that have yet to be written - now work properly. This, in turn, inspired a couple of ideas for Layer functionality, so those have been added to the To Do List.

The final task for the day way to add masking functionality to Brush mode. Currently, the user can set up a mask (like the Stencil in Dpaint) in order to prevent certain tiles from being drawn over. This had been implemented in every drawing mode except Brush mode, and though this wasn't a huge oversight, it a) wasn't very consistent, and b) seemed like a valuable addition to the toolset.

After a little bit of tinkering, the masking code was in and working, with masked tiles now displayed over the current brush as the user moves it around (this makes it easier to see what the end result will look like when the brush is plotted to the map).