Monday 31 August 2009

With good software, comes good design

Maybe... I don't know but what I do know is that all my favourite software has good design. So why not have some nice sleek design in our own software? I have been working on icons (and a logo...) for ExeSketch.
This was an idea for radial menus but David is leaving them for the future as they could be a 'mare to code. So we will be having a linear menu along the top or side of the canvas with the icons in a nice neat row.

The icons that you see here (if all goes to plan) should be in the first alpha release of ExeSketch. There is one more icon for Regular polygons too, but I can't find a nice image of it with other icons, so for brevity I will leave it out for now.

More from me later,
-James

Saturday 29 August 2009

Long time, no see; much coding, however

For some reason I completely forgot to post updates here this week. As a result, they've stacked like a pile of bills, and the mountain is about to collapse - in blog post form! I suppose the best way of introducing the huge volume of updates is by way of another demo video:

ExeSketch Demo 2 from Animatinator on Vimeo.



So, as you may have ascertained from the video, the most obvious change is that ExeSketch is now possessive of both a fully-functional Polygon class and a hyper-spiffy Circle class. However, that's not all - as well as the new objects I've added several more accessor functions to the existing ones, a generic bounding box drawing function for all objects (noticeable in the video), duplication of objects, and all sorts of items of jazzy miscellany that presently escape my memory.

Now, excuse my recapitulation of Polygon features I may have mentioned before; I'm on the "Create Post" page and can't be arsed going into a new tab to read over my previous post on the topic. All I know is that some of it is new, probably. Well, to begin with guaranteed repetition, the Polygon class defines a polygon as a series of points joined by lines or filled. In edit mode, one can select points and move them (or delete them with the delete key), and add a new point after the selected one by applying pressure through whichever finger happens to lie poised atop the rightmost mouse button. Fairly simple really, and I believe undeserving of further explanation. What's almost certainly new is completely bug-free mouseclick detection (I redid the function and it now has both the advantages of brevity and, you know, working). I also added antialiasing for polygons, something which doesn't work on my system (bloody Intel card) but may well work on others.

The Circle class, being entirely new and shiny, is a different kettle of fish entirely (for one thing, it's circular). This is defined as a position (its centre point) and a single point on its circumference, the latter of which can be moved around in editing mode in order to resize the circle. As usual, fill can be toggled with the F key; the only class that probably won't have this feature is the Bézier curve (ah, how I dread its mathematical curvy complexity).

Before I forget, duplication is done with shift-D. And that's it. Such a piddly description seems hardly worth the hours I spent trying to get the damned thing to work (don't get me started), but from a user's perspective, it really is as simple as that. And on that note, here's the source code again. Good day!

Monday 24 August 2009

Soon, my friends, there will be polygons...

Today saw a rather large amount of code being added to the Polygon class; it has now reached the point where such objects can be added to the drawing and taken in and out of edit mode. However, you can't actually edit them yet. And the function for testing to see if the mouse is within the polygon isn't done yet either. However, the fact that it draws without crashing the program is a miracle in itself.

As well as this, I messed around with some classes a bit and now, when you zoom the view, the editing handles scale also so that they remain the same size in physical pixels. This means that editing from a great distance is no longer the microscope-waggling affair it once was, and for that reason large-scale doodlers everywhere can breathe a unanimous sigh of relief.

To those still awaiting the slightly-hyped continuation of the ExeSketch Explanation, allow me to unequivocally unshroud the undeniable TRUTH: 'tis no abandoned series; I simply have not yet made my way around to doing it. It's in the works though. I've got the Blogger draft to prove it.

So, with a random fling of today's code changes in the general direction of my reading audience, with the expectancy that someone will grab it and give it to an arbitrary infant as a chew-toy serving as cause for my retention of the more awesome finished Polygon code (to be completed by next post) in my pocket, I take the customary means of leave by the leftmost end of the stage. Good night, or good morning; feel free to substitute a time zone-corrected greeting as it pleases you.

Sunday 23 August 2009

In equal scale weighing delight and dole

Which would you like first: the good news or the bad news?

Well, I'm afraid you're bound by my ordering. I'm not psychic, you know.

Every post needs to open with some kind of positivity (it's an unwritten blogging axiom (probably)), so to begin with, I'd like to point out that you can now delete objects in ExeSketch. The code is far fr
om beautiful, but it works, and that's all that really matters - certainly when there's only one person working on the code. If you'd like to gaze upon its awesomosity, you can check it out at the Launchpad page (changes since the last version of the code are highlighted). As well as this, I modified main.cpp to handle F-key events and things like page up and home. The code can be seen on the same page (scroll up!).

Now, on the more ill-inclined surface of this two-sided post, a rather problematic bug has sprung up. W
hen the window is maximised, the display is immediately stretched and mouse clicks no longer hit the parts of the screen they should. Restoring does not solve the problem; indeed, it makes it worse, as the display then shrinks and the mouse clicks hit targets even further from those aimed at. The problem is illustrated in the image to the right (click to view it full-size).

The bug report can be found here. I'll update that page with any progress I make, but at the moment the problem is looking close to unsolvable, unfortunately (unlike a similar problem with minimising which was fixed with one line of code). I'll see what I can do though.

And on that negative note, I end. That's the difficulty with two-sided coins: you either start badly (breaking the ExeSoft Blogging Law) or end badly. And in this case, I choose the latter. However, all is not lost: click here to regain your former joy!

Saturday 22 August 2009

ExeSketch: Now on Launchpad!

As of today, ExeSketch now has a Launchpad project page for hosting its code and managing updates and changes - you can find it at launchpad.net/exesketch. Thanks go to James for setting it up, and providing assistance for those of us who don't have a clue about how to use that sort of thing (i.e. myself).

From now, the Launchpad page will be used to store the source code, as well as to manage bugs ("Bugs" tab) and intended features ("Blueprints" tab
). Meanwhile, this blog will continue to be the place to go to for development news, updates and the occasional ramble (inevitable, I'm afraid).

And, shockingly, that's all there is to say on the matter. I suppose this must be some sort of milestone, being as it is the shortest post in rather a long time, so to celebrate, here's a LOLcat:


Happy short-post day!


EDIT: It turns out that this being a short post isn't the only thing worth celebrating - at some point whilst my back was turned, the hit counter over in the right-hand column of the page surpassed 4000! Perhaps a worthwhile blog somewhere has an easily-misspelt url like "exefost" or something...

Wednesday 19 August 2009

ExeSketch Explanation: The Display

Welcome to the second instalment in The ExeSoft ExeSketch Explanation Series of Presently Undefined Length. This particular informational outpouring concerns the item of code positioned directly adjacent to the EventHandler in the chronological stream of linear storytelling. That is to say, it was the next thing I wrote. (I'm endeavouring to eschew bombastic grandiloquence. Aagh, dammit.)

This is another class whose inspiration stems from difficulties I faced implementing requested features into CurveDraw's code. The problem with CurveDraw was that the view was completely static - if something went off-screen unintentionally, it was effectively lost. The edges of the screen served as that point in a sofa where the seat-cushions meet the back-cushions, except in CurveDraw there was a bottomless pit underneath, and the cushions were sewn on meaning that any attempt at catching something was rendered impossible. And the sofa was made of spikes. Probably. Similarly, editing a curve of more than moderate intricacy would be a case of pressing your face right against the screen, magnifying glass in hand, moving the mouse as accurately as possible with both hands so as not to drag the wrong point or make a mess of the curve handles. (EDIT: Yes, I know I just filled three hands. Get a friend to hold the magnifying glass or something.) The obvious void to be found in its existing feature set was one which might have been comfortably filled by zoom and pan features; unfortunately, to code such a thing was a concept standing quite without the realms of possibility.

The issue was that points in objects were stored as pixel co-ordinates instead of co-ordinates in arbitrary 2D space, and pan/zoom would involve adding appropriate variables to the code for offset and scale and then setting up transformation functions for each object's individual points and for object centres, all of which would amount to a lot of messy coding and awkward global variable usage.

These issues are resolved in ExeSketch by defining all points in arbitrary 2D space (referred to in ExeSketch as real co-ordinates), as suggested above. Each object has a centre point defined in real co-ordinates, and the object's points are defined relative to that centre point (in local co-ordinates). When it comes to drawing, a single redraw command is sent from the main program through to the display class, ObjectDisplay, which sets up an OpenGL transformation matrix using variables it stores for the camera offset and the zoom factor. It then simply sends a redraw call to each object registered with it, and Bob's your teapot.

Another advantage of having this class to handle the display camera is that zoom and pan can be handled by event handling functions within the class, thus clearing potential clutter from the main file. (That's the reason for the EventHandler having a reference to the display object, as mentioned in the previous post explaining the event system.)

And that, as far as I can tell, is pretty much all there is to know about the display. You may have noticed I'm not going into much detail about the code that makes this stuff happen in this series; it's simply an explanation of how the myriad classes interact and why. For those interested in the code itself, the project is of course open-source; ye who seek it shall be rewarded, should you incline your browsing hither. And once again, my (transient few) readers, I bid thee goodbye.

Tuesday 18 August 2009

Quick ExeSketch demo video

As I haven't had much time for continuing the explanation of ExeSketch over the past two days (or, indeed, to code anything for it), I've done a quick video of what exists at the moment to fill the update-gap. It demonstrates the creation of a rather spiffing smiley face (with a fetching rectangle for a mouth to compensate for its lack of a nose) using the Rect primitive (because it's still the only one implemented...). Behold:

ExeSketch demo 1 from Animatinator on Vimeo.



More (proper) updates to follow soon...

Sunday 16 August 2009

ExeSketch Explanation - Events

Welcome to the first in a series of posts intended to explain the ExeSketch code I've written up to this point. As lining up the beginning of a retelling with the corresponding point in temporal space seems logical, I'll begin with the EventHandler and Event classes, which (odd though it may seem) were the first things I coded.

In truth, the event system in place wasn't made specifically for ExeSketch - initially it was just an idea I had for getting around GLUT's way of dealing with events. Having spent quite some time coding in PyGame, I've become accustomed to an event loop in which I first procure a list of all the new events with pygame.event.get(), then process them one by one, sending each one to the appropriate point in the code. In this way all the events are handled by one central function (normally just in the mainloop), which I find relatively simple to maintain. However, in GLUT, there is no user-defined mainloop - the code you write is entirely driven by GLUT events, and the way you get your code into the program's mainloop is by writing it into special functions and binding them to GLUT events.

This is actually fairly simple - to take the window repainting event as an example, you begin by writing a function RedrawScreen() (or whatever you choose to name it) and bind it to the GLUT call to redraw with glutDisplayFunc(RedrawScreen). And this works rather well for situations similar to the above. However, this system of stuffing code into designated orifices isn't particularly helpful for user events that need to be passed to several different objects, as for a fairly average application you would need to register glutMouseFunc, glutMotionFunc, glutPassiveMotionFunc, glutKeyboardFunc and glutSpecialFunc and then have every one send its events to all the appropriate objects with its own version of the event handling code. Each object would then have to have specific functions for each type of event, as each event has different arguments - mouse position, key, whether the buttom is going in or out - making event handling a process liable to wear your CTRL and C-keys out with the haste and enthusiasm of an industrial belt sander.

Being rather fond of the aforementioned keys (they really come in handy when you're writing an essay on something well-documented by Wikipedia...), I decided an alternative had to be found. And when, after much pondering, this alternative eventually came, it did so in the shape of the ExeSketch EventHandler class.

To put it simply, each registered glutFunkyFunc creates an object of type Event, which stores all the appropriate information for the event, and then passes that to a central EventHandler object. On a call to EventHandler::ProcessQueue(), any events that may have accumulated in the event handler's buffer are processed by the much-coveted single event-handling function, which does what it needs to the events before sending them off to all the objects registered with it.

However, as mentioned before, different events have different parameters supplied with them. To resolve the problems this would cause, I created an enumeration of all possible user events, which you can see here. Essentially it is written as a branched tree: At the root is EVENT, which splits into MOUSE and KEYBOARD. MOUSE then splits into UP (button up), DOWN (button down), and MOTION, with UP and DOWN splitting further into individual buttoms. KEYBOARD splits into all the possible key events, each preceded by K_. An item in this imaginary tree structure is translated into a variable name by joining its branches with underscores, for example EVENT_MOUSE_DOWN_LEFT (when the user left-clicks) or EVENT_KEYBOARD_K_S (when the 's' key is pressed). The enumeration simply defines these as numerical constants, and so they can be used to define an event type throughout the code. An Event object stores its event type as the appropriate integer, as well as two other integers: xpos and ypos. These are used to store the mouse position parameters for mouse functions, and when not needed are simply set to the integer constant NA.

Meanwhile, the EventHandler class stores a collection of these objects in an STL queue, chosen because it provides basic FIFO queue functionality and no more, which is all that is needed in this case (having nifty functions to swap/juggle/tightrope across individual items in the container would be slightly overkill). It holds a pointer to the ObjectDisplay class (to be explained in a later post) and an STL vector of pointers to ObjectManager objects (again, to be explained in a later post), to which it sends events. ObjectManagers are registered with it using a RegisterClient function which accepts the pointer to register.

The ObjectManager and ObjectDisplay objects which receive the events need only provide a HandleEvent function to deal with the Event objects the event handler sends them, as well as making themselves known with the event handler's RegisterClient function. From then on, control over user input is entirely given over to the EventHandler.

You'll have to excuse the boundless prolixity of this post, I didn't really intend for it to end up as long as this. It was alyways going to be the longest in the series anyway; the next ones should be shorter. If you stuck with it as far as here, congratulations! You have a God-like attention span. To the rest of you, I'd like to take this opportunity to recommend a nifty online utility I found a short while ago for reading long things incredibly quickly - Spreeder. Essentially you copy the text to read into the box, and it displays it word by word at several hundred words per minute (you can set the speed to whatever is readable). By this approach you avoid problems like being slowed down by line breaks, unintentionally casting your eyes backwards along a line and the dreaded subvocalisation, which means that you get through the text a lot faster whilst still retaining almost as much as you would normally.

It's useful for quickly digesting blog posts written by people who need to learn the art of brevity.

Saturday 15 August 2009

Reworking the spaghetti

Bear with me as I affectedly ignore the fact that two posts on consecutive days constitutes a supernal feat not reached by this blog in almost a year.

Today's coding progress mainly comprises alterations to the
ObjectManager class, which is responsible for holding a group of objects and sending them redraw commands and events, and returning to its parent such information as whether or not the mouse is hovering over one of its subordinate objects. As is by now ExeSoft tradition, bugfixes and feature modifications had by this afternoon driven the former beauty of the HandleEvent() function deep into the seething droves of, ahem, faecal matter, which are to be found in the realms of spaghetti-like entanglement and fractallic code-nesting.

And so, driven by the view that CurveDraw's sequel shouldn't face hereditary messiness, I spent some time re-working the code in an attempt to make it legible. And a success it was, for to my eyes at least the code now seems a lot less mucky. It's still verging on a hundred lines for the one function, but that should change as I break some of its tasks up into sub-functions (and perhaps further simplify what it's doing).

However, it's not all invisible behind-the-semi-functional-scenes stuff in this instalment; I also added a new feature. Behold the glorious power of object re-ordering:



This solves an irritating problem frequently encountered when multiple filled shapes conglomerate in an image: now, you needn't bother carefully regulating the order in which you add objects to the scene so as to keep the background at the back, because with a single tap/hammer/rocket-propelled incineration of the arrow keys you can deftly alter the ordering of any objects in the drawing. This is done with a bit of fiddly pointer-juggling - you can see this part of the code here.

For now, I depart, leaving only the (by now dubious) promise of another post in the near future. Although many will be inclined to incredulity, I assure you that unless major difficulties are encountered, this blog should now continue as it once did (before the recurring failures to update). If I don't post again within a week or so, do feel free to provide a text-based kick via the comments section.

As before, the source code for the entire project is available at exesoft.awardspace.co.uk.

Friday 14 August 2009

ExeSketch (and yes, I'm still alive)

In an intermission to the vapid vacuousness of a presumably perpetual hiatus, I write this posting to once again acknowledge my own failure to maintain any sort of consistency in update frequency, and simultaneously to reveal to you a new project which serves as a sort of culmination of the long period I have spent attempting to gain some basic understanding of the syntactical intricacies and idiosyncrasies of C++ (which I hitherto had only the most rudimentary of aptitudes at). This, I may add, has proved rather successful, as that language, which was once as alien to me as this slightly ridiculous writing style I've chosen to adopt today may seem to any sane person, now seems as natural as the aforementioned ludicrously lavish lexicon usage (which I must at this point apologise for) does to myself at this particular moment.

So, with one hundred and forty-one words wasted on wanton waffling, and this post's 'ramblings' tag quite successfully earned, the time has come for me t
o take the next logical step in post-writing and endow upon you, the reader, the purpose of the bandwidth this page consumes.

The process of ExeSket
ch's development began quite some time ago, at my discovery of Beziér curves. The Wikipedia page linked to by the end of the last sentence provides the best explanation I've yet read of how they work, and armed with the provided understanding I set about implementing them in Python, using Pygame (naturally). The result can be found here.

From there, I took the concept further and developed a small drawing application, CurveDraw. It used discrete Bézier curve objects, each of which was made up of a series of joined curves, which could be used to build up drawings. The program grew to incorporate linear transformations such as rotation, and it came to the point where the code represented a toy car modified to transport cities of people to the Moon - in essence, a mess of awkward modifications and additions. So, at the point where someone suggested adding different types of shapes, a concept unthinkable with the program's existing code base, I decided that the program would have to be coded anew with a full drawing program as the intention from the outset.

Such a program
would fail to take shape for some time, and in the intermittent weeks I set about learning how to *properly* code in C++ (split infinitives included at no extra charge). I commenced to swiftly seek out tutorials, which I went on to carefully follow until the time came when I was to gradually procure an appreciation for the language whose documentation I was to systematically peruse.

So, that done, I went on to learn OpenGL - a graphics library which turned out to be much simpler to use than I had previously anticipated. Within a relatively small period of time I had managed to create an only semi-glitchy camera lookaround demo, with various cubes spinning around in the sky (about their own individual axes, after a bit of fiddling!). And after deciding that I probably lacked the mathematical calibre needed to make a full 3D game engine with cutting-edge graphics and high-tech shaders, I thought I might as well have a go at 2d for a bit.

Which led me to ExeSketch. It seemed a
s good a time as any to write the fatalistic sequel to CurveDraw, and as good a way as any to test whether I actually knew enough C++ to do it properly. This particular project involved a large amount of planning (well, in comparison to the thirty-seconds-ish I've put into other coding projects in the past), and some of the largest compiler error outputs I've ever seen (I tried to compile it all before I had written the Vector2d class which I had promised the compiler, and it spent a good five minutes vomiting forth garbled attempts at explaining what was wrong). However, after a few weeks of coding I've finally managed to get a basic version of the program running.

The program works in two
modes: Object View, and Editing (as inspired by Blender 3D, a program which provided ideas for much of the user interface of CurveDraw). In object view, one can select objects and drag them around, (ultimately) add/delete objects, and possibly apply linear transformations (that's still waiting on implementation). In edit mode, you can drag the points which form whatever object you're editing - currently the only object implemented is a Rect, which has four corner points which can be dragged to resize it (you can also press F to toggle whether or not the rectangle is filled). Panning and zooming are done with the mouse: click-and-drag and middle-click-and-push-in-or-pull-out, respectively.

The current source code is available from exesoft.awardspace.co.uk, and requires OpenGL and GLUT to compile. According to a line-counter script I wrote, it's 1136 lines so far, which I believe is an ExeSoft record (fair enough, given that I've mainly used Python up until this point). More updates are to come (if all goes well), and I might post an explanation of how ExeSketch works in the near future; for now, however, I must take my leave. Ta-ra!