Project Frontier #16: Interface’d

By Shamus Posted Wednesday Jul 13, 2011

Filed under: Programming 87 comments

I need something handy that will let me change program options without needing to compile. Right now I have everything bound to mysterious and unexplained hotkeys. There are enough of these that I’m getting confused. Hotkeys are great for turning things on and off, but terrible for fine-tuning options. It looks like I need some sort of interface for my program.

This computer interface is notable for the upper-arm and back conditioning required to use it. The upside is that, if it’s adopted, Photoshop artists will eventually look like bodybuilders.
This computer interface is notable for the upper-arm and back conditioning required to use it. The upside is that, if it’s adopted, Photoshop artists will eventually look like bodybuilders.

Now, I’m always banging on about how libraries should be as focused and unencumbered as possible, how you shouldn’t need to go on a multi-stage fetch quest to get the thing to compile like you were trying to assemble the pieces of the Tri-Force or something. The problem is, there is pretty much no way around this. Interfaces need to use fonts, and fonts are fiendishly complex beasts. Interfaces need to render stuff, and rendering is complicated. They need to process keyboard and mouse input, and those are complicated. (It seems simple, but tracking keyboards and mouse wheels and all the different things that can happen with the CTRL, ALT, and NUMPAD… it gets very hairy.) That’s a lot of things for one library to do, on top of running a window system with buttons and scrollbars and the ability to tab between interface elements and all of the other tiny details that we all take for granted.

Still, the inability to adjust options is really killing my productivity. So let’s see what we can find.

Let’s see. We need an interface system that works with OpenGL. We’ve got Crazy Eddie’s GUI system, FLTK, GLAM, GLUI, GL Gooey, LibUFO, Qt, Turska, wxWidgets… and probably others.

Wow. That is a very daunting list. Some of these libraries won’t have the functionality I need. Some will, but will have horrible dependency issues (some may even encapsulate others, or be forks of other items in the list, I don’t know yet) that will make them prohibitively difficult to use. Others will have horrible C++ interfaces that make a cluttered mess of your code. Some will have the functionality I need, but will lack the visual customization I need. (I know a few of these are designed to create standard “windows” style interfaces, which would look just awful floating atop my Seussian fantasy world.) Some might have all of the above, but be tied to a particular platform. Or lack proper documentation. Or turn out to be long-abandoned projects that no longer work due to shifting technology.

I could easily burn a couple of days downloading each and every library, getting it to (hopefully) compile, testing it out, evaluating the interface, the looks, reviewing the documentation, and making sure it actually has all the features it claims to have. (I don’t want to install the thing into my project and three days later discover that something fundamental like “text input boxes” is still on the to-do list.) This promises to be a massive investment of time. The truth is, I’m not ready to make this kind of commitment. Really. It’s not you, it’s me. I just can’t afford to be tied down at this point in the development cycle.

I began this project as a tech demo, that could become a game. But the tech demo comes first. And adding a all-singing, all-dancing, multi-window interface falls way, way outside of that scope.

Thinking about this more, what I really need is a “Quake-style” console. If you ever hit the tilde key in Quake, you probably saw the text window that opens up. That window lets you enter commands, change variables, and generally control the application without needing menus and scroll boxes and the like. This is exactly the reason console windows exist: For the proof-of-concept / prototyping stage of a project.

I ask Google, and it brings me this: glConsole.

The bad news is that it was developed on another platform (Linux, I suspect) and there are no binaries available. So I’m going to have to get it to compile. It uses CMAKE, which is supposedly a totally cross-platform system for compiling code, a claim of which I am mildly skeptical. Well, it can’t hurt. Let’s see how this goes…

(Two hours later.)

I return to you a changed man. Everything I knew was wrong. CMAKE took a little self-education to use, but once I had the knowledge it did its job flawlessly. There was an odd compile problem where glConsole complained that it didn’t match it own version number or some such piffle, but commenting out a couple of lines fixed that right up.

Let me tell you about glConsole…


It works. It works beautifully. It works seamlessly. It dropped directly into my project with no additional dependencies. It displays text, but I have no idea how. I don’t see a bitmap among its resources and it doesn’t do any font loading. It just magically makes text. I suppose I could look at the source, but so far there’s been no reason to do so. I was able to add it to my project in, I kid you not, five lines of code. I tell it when to open and close. I tell it when to draw. I feed it keypresses. That’s it. Done. I don’t even need to initialize it.


Even better, it comes with a bunch of other features:

  1. Built-in environment variables. I create them and access them at will. It keeps track of them for me, saves them, remembers them between sessions. It even has auto-complete, so it can remind me of my own variable names while I’m typing them in the console.
  2. Environment variables can be organized into groups. I have one group: render.wireframe,, and render.textured. And another group: mouse.invert, and mouse.sensitivity. This system can plug into another, so when I DO add a full-featured interface, I’ll already have all of the functionality implemented. I’ll just need to have the interface change the already-existing environment variables and it will be done.
  3. It can save options into any file I like. It can save groups or sub-groups of options. So, I can stick all of the player data into a group: player.position, player.heading, player.camera_zoom, etc. Then I can save all of the player.* options into a file. Boom. My save-game system is done, and I wasn’t even planning on working on that this week. I got it done as a side-effect of adding this library.
  4. It keeps a command history, which persists between sessions. So, I open up the console window and hit the up arrow to cycle through previously typed commands, even if I closed the program since I typed them. This is incredibly useful when I’m debugging and iterating very quickly, needing to try the same options over and over.
  5. I can execute functions from within the console. So, I can have commands to save the game, load the game, restart the rendering subsystem, purge texture data, or whatever else is needed for testing.


I’m dumbfounded. Not only did this library perfectly and seamlessly solve the problem I had in mind, but it solved future problems I hadn’t yet considered. Author Gabe Sibley has shamed me as a coder. I’ve used hackjob libraries downloaded from the internet. I’ve used enterprise level solutions that cost tens of thousands of dollars to license. And nothing I’ve ever used as been as smooth to integrate and intuitively designed as glConsole.

“If I could write software like that, I’d call myself a programmer.”



From The Archives:

87 thoughts on “Project Frontier #16: Interface’d

  1. Halceon says:

    It sounds like Gabe is using the force, magic, ritualistic sacrifice and prayer groups to power his library. Really, it sounds too awesome.

    1. Will says:

      ‘Programmer’ is secretly code for ‘Wizard’, one of the best kept secrets of the era is the fact that computers actually run on black magic.

      1. Nathon says:

        It’s magic smoke. Don’t let it out.

        1. Eärlindor says:

          It's magic smoke. Don't let it out.

          This. ^^^

    2. CTrees says:

      He took the same route Hot Toys did for their scary realistic action figures – he sold his soul to the devil.

      No other explanation.

    3. Winter says:

      My guess is that “Gabe” is a pseudonym for “John”, and “Sibley” is a pseudonym” for “Carmack”.

      It’d make sense, right?

    4. Ayegill says:

      Maybe he sold his soul to the devil at a crossroads in exchange for programming skill?

  2. Hi.

    I must confess, I haven’t read the whole post yet (*hermph*work*rmbl*) – but I was reminded of GWEN* (by Garry of Garry’s mod). Haven’t had a look at it yet, but he says stuff you/we/they like about simple and lightweight and namespaces etc.

    I know you’ve probably committed to glConsole and that GWEN is not a console UI – but this is just a heads up kind of comment. For another project or something.

    Keep up the good work. :)


  3. FunnyMoneyGuy says:

    Assemble the Tri-Force. -snicker-

    Also, that code library totally does sound awesome.


    1. Alexander The 1st says:

      This is exactly the reason console windows exist: For the proof-of-concept / prototyping stage of a project.

      So…exactly why do PC games (Portal, Fallout 3/:NV, etc.) keep it in?

      I know Descent/older RTS’s had ‘chat codes’ which in single player gave you cheat capabilities, but nothing along the line of a full on console, that I remember, at least.

      EDIT: Sorry, reply where it was suppose to be its own post.

      1. droid says:

        Maybe because in the early stages it helps in debugging the game, and the it’s too much hassle to put it in before a demonstration and take it out afterwords.

        The real answer is probably “Why not?”.

      2. Irridium says:

        Well, probably because it’d be too much of a pain to just remove. Or there just isn’t much reason to remove it.

        Or if it’s in Fallout 3/NV’s case, they leave it in because they know something will break, and this way you can fix it if needed.

        1. Bryan says:

          Or maybe, like Shamus’ solution, removing it means writing new save game code.

      3. CTrees says:

        My guess is: 1) people like them – they’re an easy way to get all your cheats (hello, Elder Scrolls/new Fallout games) and 2) in case there’s an unexpected error while a user is playing (door to a vault won’t unlock, perhaps?) it provides a very easy way for users to handle the bug, giving the developer a little bit of leeway to point towards as a temp fix to keep players happy-ish. Less angry, anyway.

        1. Shamus says:

          I imagine they’re also handy when making mods.

          1. SharpeRifle says:

            Be annoying for the developers to take it out and put it back in all the time too. I mean most DLCs are just “mods” for games anyway.

          2. MadTinkerer says:

            This is a big reason why the console is included in the Source engine. Right now, there’s no option in the GUI to manually change multiplayer levels in Portal 2. The host has to type “changelevel [name of level]” in the console. It’s also how all of the cheats are implemented, et cetera.

            Other than the options menu, loading & saving, and so on, the console is the GUI for the Source engine. Everything you need to just play the game is in the menus. Everything else is a console command. Once you have a few commands memorized, it’s a snap.

            EDIT: Oh yeah, the other big thing is error reporting. All errors and some miscellaneous feedback (like “game saved successfully”) will be put in the console window. It’s handy even if you’re not modding/debugging to see if playing normally is causing any errors to pop up, as they sometimes do right after an engine update breaks some minor feature of a level that they missed in testing.

            EDIT 2: Oh yeah, and I’m sure it’s handy for porting to other platforms. No platform-dependent GUI (or small, simplified GUI for the main game + console for everything else) means more time actually making the game.

      4. krellen says:

        Because gamers like cheat codes, and don’t like being robbed of cheat codes they could have.

      5. Hitch says:

        But the console window doesn’t exist on consoles, right?

        1. acronix says:

          Oh, the irony!

      6. Gndwyn says:

        Because there’s never a stage in the project, including after the game has shipped and users start reporting bugs none of your testers found, that a console isn’t useful.

      7. silver Harloe says:

        “So…exactly why do PC games (Portal, Fallout 3/:NV, etc.) keep it in?”

        because any change to your code – including removing debugging code, has the potential to introduce new bugs and/or otherwise subtly alter behavior :)

      8. Andrew says:

        Because both of those games were built to support user-developed mods, which will be going through their own proof-of-concept/prototyping stages. That’s my theory, anyway.

      9. decius says:

        Because taking out the console is a significant change, which would require debugging afterwards; the debugging of ‘console removed for production’ would clearly have to be done without the console.

        It would require beta testing every feature of the release version over again, roughly doubling the testing requirements.

        Removing user access to the console could be done in an undocumented setting file, but why bother?

  4. Arkady says:

    Serendipity is awesome, isn’t it? I love it when things kind of fall into place like that. It makes me feel good for days at a time.

  5. Jarenth says:

    This post series is quite rapidly turning into a useful guide book for aspiring game creators. ‘This is a thing you have to so at some point. This is what I did, and how and why it works for me. Here are some alternatives that might work better for you. Ask your doctor if Zombrex is right for you.

    I know that if I ever give in and start a (probably terribly ill-conceived) game creation project, I’ll revisit this post series for sure.

    1. benjamin says:

      my tough exactly, this series is incredibly useful and impressive.

      I’m a bit worried for the save system, will it be still practical when a lot of data will cluter the save file (hp,inventory,ect …)?

      if I may, will we have a post on the sky system? I’d like to know how you made the day/nigth system.

      1. Arkady says:

        I believe he commented briefly on it in a video (week 3, perhaps? More likely week 4… well that covers both options).

        Essentially it’s just a time-dependant lighting system.

  6. Primogenitor says:

    So I guess the moral is “use code by robot rocket scientists”.

  7. Glenn says:

    Finally, using pre-made external libraries goes right for once.

  8. Dys says:

    Ever heard the phrase ‘too good to be true’?

    If it’s this good, it must be doing something truly horrible in the background. I’m guessing it contains code that makes your program part of a vast, world spanning, cloud based self aware computer god.

    1. GTRichey says:

      In this case I for one welcome our computer overlord’s… I did a couple years of a comp. sci. degree and was always terrible at getting libraries that I didn’t write to work properly… this being when the libraries are largely given to you by the professor (which means not having to track them down which can be a monumental task).

    2. Hitch says:

      In this case I think Gabe Sibley just created something so unsexy as to be really good. He didn’t put in any GUI, any graphics, any bells and whistles… who would ever want this? Just people who want simple functionality, but most programmers know that people like that don’t exist.

    3. DrMcCoy says:

      If it's this good, it must be doing something truly horrible in the background.

      Depends. GLConsole, being the monolithic and easy to use thing it is, has of course certain limitations.

      If you’re okay with the default behaviour, it’s of course a great library. However, if you want it to use a specific font, or use your authorative event queue for input reading, or would like special keybindings like the readline/emacs-type ones, want it to read the history from something other than a plain file, etc., vanilla GLConsole is not for you. You’d either want to modify it, look for something different or roll your own. :P

    4. You say that like it’s a bad thing.

    5. Joe Cool says:

      Maybe “Gabe Sibley” is a pseudonym for Matthew Sobol, and glConsole is part of his Daemon.

      (I wonder how many people will get that.)

      1. mike says:

        At least one.

  9. William Newman says:

    Shaming as a coder is one of those resources like irony and mistakes
    that the universe supplies in surprisingly generous quantities: TeX,
    Doom, Dunkosmiloolump, git, several Google products, etc.

    Maybe I could see further if I weren’t in the shadow of giants!

    Also, on a different note, surely a post about consoles should reference
    Neal Stephenson’s _In the beginning was the command line_.

  10. bickerdyke says:

    Photoshop artists already can make themselves look like bodybuilders……

    1. Epopisces says:

      All too true.

    2. Pickly says:


      (Laughing quite hard here.)

  11. sab says:

    At the beginning of this post I thought “Tsk, why not just use an ini file? It’s easy to adjust, even for possible endusers, and it won’t require recompiles.”
    I giggled when you mentioned all sorts of possible libraries, that would no doubt bring endless clutter, thinking “No way /our/ Shamus would us those”.
    Then when I saw the glconsole screenshots and explanation, I was baffled. For the umpteenth time in the saga of Project Frontier.

    Way to go, sir.

    1. Shamus says:

      I actually have been using ini files until now, but it’s not really a good way to to (say) turn off texturing. I’m probably going to rip out the ini code (it’s all Microsoft API calls anyway) at some point.

  12. DrMcCoy says:

    It displays text, but I have no idea how. I don't see a bitmap among its resources and it doesn't do any font loading. It just magically makes text

    It uses glutBitmapCharacter().
    It also uses GLUT for keyboard input. I’m a bit surprised that doesn’t clash with SDL also monitoring keyboard input.

    1. Shamus says:

      I does? It requires my to send it input. (Thank goodness, I don’t want it intercepting input.) Maybe there’s an option to have it manage its input. Or maybe this is because I created the window via SDL and not Glut.

      1. DrMcCoy says:

        Ah, okay, using KeyboardFunc(). This still calls glutGetModifiers() to get the currently active modifier keys, though.

  13. jwwzeke says:

    Question: Are the dark patches on the ground shadows from cloud cover… or just a different color of dirt?

    Over the last few posts I had been seeing those and assuming that it was a lighting effect due to clouds… but most of those images were closer shots with not much sky visible. The first one in this post has those ‘patches’ but I’m not seeing clouds.

    Second question: If those are just dirt patches, when you do eventually add sun and clouds, can these they please cast shadows on the ground like that. They look great. :) Probably not an easy task… but the world would look great with cloud shadows rolling over those hills.

    Oh, also, I am definitely going to take a look at glConsole.

    1. Shamus says:

      Dark spts are just dirt, contrasting with sand.

      I haven’t decided on a shadowing system yet.

      1. Octal says:

        It looks kind of like an army of shadows is swarming out from under the grass to converge on and devour the player.

        1. Ayegill says:

          Now shamus will have to include monsters whose only visual manifestation is an eddy in the lighting system.

          1. Octal says:

            Who’s Eddy?


            That would be kind of neat, though.

  14. HeroOfHyla says:

    I keep forgetting the amazing extent to which my graphics experience is with incredibly simplified tools. With Game Maker (which has a coding language with fairly Java-like syntax) you just draw_text(x,y,string) to make text show up (there are other functions like draw_text_transformed and draw_text_ext for more options). And it has a built in “debug mode” where it runs a second window at the same time as the game where you can track and change any variable.

    Even Java has stuff like much easier file importing and tons of built-in libraries for gui components and sprite drawing.

  15. Leon says:

    Is that the finished avatar? He’s lookin’ good.

  16. Dev Null says:

    Definition of a well-designed library:

    I suppose I could look at the source, but so far there's been no reason to do so.

  17. Kdansky says:

    Not to rain on your parade here, but what about licencing? Currently, you’re closed source and don’t even sell it to anyone. But if you would want to go commercial, external library licenses can put a damper on that. Especially the virus-like GPL. This one is LGPL, as far as I can tell, so that’s still fine, I believe.

    1. I’m personally very fond of the GPL so I wouldn’t use that adjective. But the point is valid–a GPLed library, or a few other licenses, could interfere with going commercial.

      1. Kdansky says:

        If you use a GPL-library anywhere, you are forced to go GPL yourself. GPL works fine until you start writing software for a living, at which point it becomes a huge “implement it yourself (or be my bitch)!” sign.

        1. DrMcCoy says:

          Well, the thing is, without that other person / group writing the library for you, you would have to implement it yourself anyway.

          What alternative do you prefer, then? People always putting their code under a BSD-style license? As a FLOSS contributor myself, I certainly can understand that someone doesn’t want to see their code changed/adapted/improved but then no one else being able to benefit from those improvements.

      2. perry says:

        well, gpl IS viral. whether or not you’re a fan is immaterial. it is intentionally designed to be viral.

        1. DrMcCoy says:

          Except that it doesn’t infect other code on its own, so the metaphor is rather…wonky.

          All it does is that information that is free (as in speech) stays free and when someone did something cool to improve on it, that information should be free too. If you want to call that “viral”, that’s your choice but I for one think that’s a rather mean-spirited word, what with its connotations and all.

          Of course, the strict GPL does mean that using GPL’d libraries in a non-compatible licensed project does not fly. That’s why there’s the LGPL. In fact, off the top of my head, I can only name one common library that’s GPL instead of LGPL, libmad.

          1. Kdansky says:

            Except it does infect licenses. Of course it doesn’t touch code, it’s a license! The thing is that I cannot use a GPL library and keep my own code closed. I have to open up code that the GPL user didn’t even write.

            It doesn’t get much more viral than “force other people to change their license”.

            Good? Bad? Depends. But it is designed to be viral.

            1. DrMcCoy says:

              Force? Well, nobody forces you to use code you didn’t write in your project…

              1. Kdansky says:

                Good, because that is entirely besides the point.

                1. DrMcCoy says:

                  I don’t think it is. To be considered “viral”, it would have to infect things on its own and spread. Like, you know, a virus.

                  If you however make a conscious choice to use code written by someone else and build upon it, that you then have to adhere to the license is not viral.

                  1. silver Harloe says:

                    Correct. the term “viral” doesn’t apply. The GPL doesn’t come and infect your code, you make a decision to use GPL’d code yourself. GPL infects my code like Pizza infects my stomach – only if I want it to.

                    On the other hand, it’s hard to call GPL’d code “free” (in either sense) because it doesn’t come free of restriction, it comes burdened down with restrictions. Fortunately, the LGPL exists for the majority of people who don’t get paid to release software to the world, but get paid to make software just for their company.

                    Even more fortunately, I’ve always worked on websites, where we use software but never release software, so I’ve never really had to decide whether to recode a handy library or not :)

                    1. DrMcCoy says:

                      Depends on how you define “free”. The restrictions are there to keep information in the open. A necessary “evil”, in my eyes.

                      The GPL and the LGPL are two different parts of the same thing. The GPL is for stand-alone programs, the LGPL is for libraries. Both require you to make changes to the actual code open under the same license. I.e. if you change the actual code of a LGPL’d library, you still have to make those changes public. The only difference is that the LGPL allows you to, from your stand-alone program, link against the library without having to make said stand-alone program (L)GPL too. The LGPL is basically just an extra clause needed due to the unique nature of libraries.

                      As such, there is no actual GPL vs. LGPL “dispute”. GPL is for stand-alone programs, LGPL for libraries. You’ll be hardpressed to find more than a handful of libraries that are GPL instead of LGPL (like I said above, the only example I can think of is libmad).

                    2. krellen says:

                      I believe the usage of “viral” here is as in “viral video”.

                    3. decius says:

                      The term “viral” certainly does apply to the GPL. GPL software easily enters other software, through the actions of programmers. The software becomes GPL, and must be published in such a manner as to be free to infect other software.

                      Just because it does all this in the presence of active human assistance doesn’t make it less viral. Many biological virii require active assistance from the cells they infect.

  18. StranaMente says:

    The last screenshot reminds me of Frozen Synapse ( By the way, Shamus, I have a copy spare on my steam account (they only sell this game in couple for some odd reason) would you like it?

    1. StranaMente says:

      Or maybe someone else in the spoiler warning crew?

      1. krellen says:

        I’m not a big fan of simultaneous turn-based (why does everyone keep trying to incorporate “twitch” gaming into everything?). Is there a way to set it to just regular-old turn-based?

        1. StranaMente says:

          I don’t know, besides i think it might spoil the fun of trying to figure out what to do next, but I saw that there several game modes in it.

        2. Frozen Synapse has no “twitch” gaming. Old-fashioned turn-based would actually ruin what the game does, which is trying to use tactics to determine what your opponent will do.

          You each take your turn by giving orders, but you don’t see the orders given by your opponent. Then, when you’ve both accepted all your orders, the game runs both turns at once and you see what happened. Then you both go back to taking turns.

          That’s why the game allows you to play over e-mail.

    2. droid says:

      I also have an extra copy.

  19. UbarElite says:

    So, what was looking to cost you a lot of time, actually ended up saving time in solving future problems already?

    Life can be very cool sometimes.

  20. Gndwyn says:

    It makes me so happy to see you making such steady and significant progress, Shamus. I hope you’re finding it satisfying and rewarding, and I’m really looking forward to whatever you end up releasing.

  21. Aldowyn says:

    This post contrasts so much with every single other post you’ve made in reference to using outside libraries.

    I’m glad that was so easy for you, Shamus! :)

  22. Glen says:

    Once you get to the stage of working on a real GUI it might be worth looking at awesomium ( The Overgrowth guys use it to good effect.

    1. StranaMente says:

      And I thought that name was a funny placeholder…

    2. Zak McKracken says:

      I just wrote in the last post’s comments what a pain it must be to store your textures in SVG images … but awesomium can render into 3D textures, includes the chromium engine, and chrome renders SVGs, so there you go … crazy.

  23. Zaghadka says:

    This entry made me smile. +2 library of awesome.

  24. Bah says:

    Despite not being to a point in our project to worry about such things, Shamus’ praise of glConsole was so strong I thought I may as well get it in now… most of a day later I’m pulling my hair out. I don’t want to sound like I’m blaming Shamus for gushing about an awesome tool I don’t understand, but I’ve only ever worked in IDEs(MSVC++ atm), and just don’t know how cmake is supposed to work.
    Will this compile a codefile I keep in the project?
    Will it stick a folder in the bowels of windows that I need to include like OpenGL?
    Am I going to need to compile part in VC and finish with a console command to cmake every time I build?
    I’ve had no luck with tutorials. Everything is so balkanized, every implementation so different, so much different terminology, that I can’t tell what’s signal, it’s all noise. Maybe it’ll all be clearer tomorrow, but any help would be very much appreciated.

    1. Shamus says:

      CMAKE should create a Visual Studio project file, which you can then open and compile.

      1. Bah says:

        Many thanks, got it. OMG CMAKE HAS A GUI. The app is in the bin folder in the cmake dir, and I had no reason to look there. Once I found that it was easy as silk. Need to figure out makefiles someday, but for now, I appreciate VC++ ALOT more.

  25. I’d like to find out more? I’d care to find out more details.

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun. Your email address will not be published. Required fields are marked*

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>

Leave a Reply

Your email address will not be published.