implement --help, --fullscreen, --resolution and --list-modes
authorTero Marttila <terom@fixme.fi>
Tue, 13 Jan 2009 20:17:03 +0200
changeset 389 e74c1820fbd2
parent 388 ecb243eebc25
child 390 3c8078b96469
implement --help, --fullscreen, --resolution and --list-modes
src/Application.cc
src/Application.hh
src/Config.hh
src/Engine.cc
src/Engine.hh
src/Graphics.cc
src/Graphics.hh
src/Input.cc
src/Input.hh
--- a/src/Application.cc	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Application.cc	Tue Jan 13 20:17:03 2009 +0200
@@ -2,24 +2,58 @@
 #include "Application.hh"
 
 #include <stdexcept>
+#include <cstdio>
 #include <cassert>
 
+enum ArgumentCodes {
+    ARG_HELP        = 'h',
+    ARG_PORT        = 'p',
+    ARG_SERVER      = 's',
+    ARG_CLIENT      = 'c',
+    ARG_GRAPHICS    = 'g',
+    ARG_FULLSCREEN  = 'F',
+    ARG_RESOLUTION  = 'R',
+
+    ARG_LIST_MODES  = 0xff01,
+};
+
 
 /**
  * Set the arg_* members
  */
-void Main::parse_args (int argc, char **argv) {
+bool Main::parse_args (int argc, char **argv) {
     // set up the options
-    args.add_option('p', "port", "PORT", "set network port used", true);
-    args.add_option('s', "server", "", "act as a network server", true);
-    args.add_option('c', "client", "SERVERHOST", "act as a network client", true);
-    args.add_option('g', "graphics", "", "run graphics/local input. Implied with --connect", true);
+    args.add_option(ARG_HELP, "help", "",
+            "display argument help and exit");
+
+    args.add_option(ARG_PORT, "port", "PORT",
+            "set network port used");
+
+    args.add_option(ARG_SERVER, "server", "",
+            "act as a network server");
+
+    args.add_option(ARG_CLIENT, "client", "SERVERHOST",
+            "act as a network client");
+
+    args.add_option(ARG_GRAPHICS, "graphics", "",        
+            "run graphics/local input. Implied with --connect");
+
+    args.add_option(ARG_FULLSCREEN, "fullscreen", "",
+            "run graphics in fullscreen mode");
+
+    args.add_option(ARG_RESOLUTION, "resolution", "WIDTHxHEIGHT",
+            "set graphics resolution");
+    
+    args.add_option(ARG_LIST_MODES, "list-modes", "",
+            "output a list of available display modes and exit");
 
     // set defaults
     arg_graphics = false;
     arg_port = NETWORK_PORT_STR;
     arg_server = false;
     arg_connect = "";
+    arg_fullscreen = GRAPHICS_FULLSCREEN;
+    arg_resolution = PixelCoordinate(GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT);
 
     // extra state
     bool graphics_default = true;
@@ -34,22 +68,38 @@
 
     while (args.next()) {
         switch (args.get_key()) {
-            case 'p':
+            case ARG_HELP:
+                args.print_help();
+                return false;
+
+            case ARG_PORT:
                 arg_port = args.get_argument();
                 break;
 
-            case 's':
+            case ARG_SERVER:
                 arg_server = true;
                 break;
 
-            case 'c':
+            case ARG_CLIENT:
                 arg_connect = args.get_argument();
                 break;
 
-            case 'g':
+            case ARG_GRAPHICS:
                 arg_graphics = true;
                 break;
 
+            case ARG_FULLSCREEN:
+                arg_fullscreen = true;
+                break;
+
+            case ARG_RESOLUTION:
+                parse_arg_resolution(args.get_argument());
+                break;
+
+            case ARG_LIST_MODES:
+                dump_display_modes();
+                return false;
+
             case CL_CommandLine::REST_ARG:
                 throw ArgumentError(args.get_argument());
 
@@ -66,6 +116,29 @@
     // enable graphics by default unless server
     if (!arg_server && graphics_default)
         arg_graphics = true;
+    
+    // continue
+    return true;
+}
+        
+void Main::parse_arg_resolution (const std::string &val) {
+    unsigned int w, h;
+    
+    // sccanf as unsigned
+    if (sscanf(val.c_str(), "%ux%u", &w, &h) != 2)
+        throw ArgumentError("invalid format for --resolution");
+    
+    // store as PixelCoordinate
+    arg_resolution = PixelCoordinate(w, h);
+}
+        
+void Main::dump_display_modes (void) {
+    const std::vector<CL_DisplayMode> &modes = Graphics::getDisplayModes();
+    
+    std::cout << "Available display modes:" << std::endl;
+
+    for (std::vector<CL_DisplayMode>::const_iterator it = modes.begin(); it != modes.end(); it++)
+        std::cout << "\t" << it->get_resolution().width << "x" << it->get_resolution().height << std::endl;
 }
 
 /**
@@ -79,15 +152,16 @@
     CL_SetupGL setup_gl;
 
     try {
-        // parse arugments
-        parse_args(argc, argv);
+        // parse arugments, exit if false
+        if (parse_args(argc, argv) == false)
+            return 0;
 
         // our engine
         Engine engine;
         
         // setup graphics
         if (arg_graphics)
-            engine.setupGraphics();
+            engine.setupGraphics(arg_resolution, arg_fullscreen);
 
         // setup either network server, client or singleplayer
         if (arg_server) {
--- a/src/Application.hh	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Application.hh	Tue Jan 13 20:17:03 2009 +0200
@@ -39,11 +39,33 @@
          * --connect
          */
         std::string arg_connect;
+
+        /**
+         * --fullscreen
+         */
+        bool arg_fullscreen;
+
+        /**
+         * --resolution
+         */ 
+        PixelCoordinate arg_resolution;
+
+        /**
+         * Set the arg_* members
+         *
+         * @return true if execution should proceed, false if execution should stop
+         */
+        bool parse_args (int argc, char **argv);
+
+        /**
+         * Parse and set --resolution/arg_resolution WIDTHxHEIGHT
+         */
+        void parse_arg_resolution (const std::string &val);
         
         /**
-         * Set the arg_* members
+         * Print out a list of display modes
          */
-        void parse_args (int argc, char **argv);
+        void dump_display_modes (void);
 
     public:
         /**
--- a/src/Config.hh	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Config.hh	Tue Jan 13 20:17:03 2009 +0200
@@ -117,6 +117,7 @@
 const uint32_t GRAPHICS_RESOLUTION_WIDTH = 800;
 const uint32_t GRAPHICS_RESOLUTION_HEIGHT = 600;
 const uint16_t GRAPHICS_UPDATE_INTERVAL_MS = 20;
+const bool GRAPHICS_FULLSCREEN = false;
 
 
 // Filesystem paths
--- a/src/Engine.cc	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Engine.cc	Tue Jan 13 20:17:03 2009 +0200
@@ -12,9 +12,9 @@
     
 }
 
-void Engine::setupGraphics (void) {
+void Engine::setupGraphics (PixelCoordinate resolution, bool fullscreen) {
     // create the graphics
-    graphics = new Graphics(*this, game_state);
+    graphics = new Graphics(*this, game_state, resolution, fullscreen);
 }
 
 void Engine::setupNetworkServer (const std::string &listen_port) {
--- a/src/Engine.hh	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Engine.hh	Tue Jan 13 20:17:03 2009 +0200
@@ -37,7 +37,7 @@
         Engine (const std::string resource_xml_path = RESOURCE_XML_PATH);
 
         // setup graphics
-        void setupGraphics (void);
+        void setupGraphics (PixelCoordinate resolution, bool fullscreen);
         
         // set up network server/client
         // setting up both of these will lead to odd behaviour :)
--- a/src/Graphics.cc	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Graphics.cc	Tue Jan 13 20:17:03 2009 +0200
@@ -4,11 +4,11 @@
 #include <cmath>
 #include <sstream>
 
-Graphics::Graphics (Engine &engine, GameState &state) :
-    CL_DisplayWindow(GRAPHICS_WINDOW_TITLE, GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT),
+Graphics::Graphics (Engine &engine, GameState &state, PixelCoordinate resolution, bool fullscreen) :
+    CL_DisplayWindow(GRAPHICS_WINDOW_TITLE, resolution.x, resolution.y, fullscreen),
     engine(engine), 
     state(state), 
-    resolution(GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT),
+    resolution(resolution),
     update_timer(GRAPHICS_UPDATE_INTERVAL_MS),
     input(get_ic()->get_keyboard()),
     simple_font("Font2", engine.getResourceManager()) 
@@ -21,13 +21,33 @@
     update_timer.start();
 }
 
+const std::vector<CL_DisplayMode> & Graphics::getDisplayModes (void) {
+    return CL_DisplayMode::get_display_modes();
+}
+
 void Graphics::check_input (void) {
     LocalPlayer *player;
     PlayerInput input_mask;
     TimeMS input_dt;
     
     // update gui flags
-    this->flags = input.readGuiInput();
+    handle_input(input.readGuiInput());
+
+    // stop here if we don't have a local player
+    if ((player = state.getLocalPlayer()) == NULL)
+        return;
+    
+    // build input_mask
+    input.readPlayerInput(input_mask, input_dt);
+    
+    // apply input if there was any
+    if (input_mask)
+        player->handleInput(input_mask, input_dt);
+}
+    
+void Graphics::handle_input (GuiInput flags) {
+    // update flags
+    this->flags = flags;
 
     // quit?
     if (flags & GUI_INPUT_QUIT) {
@@ -35,21 +55,18 @@
 
         return;
     }
-     
-    // stop here if we don't have a local player
-    if ((player = state.getLocalPlayer()) == NULL)
-        return;
+
+    // dump player debug info on stderr
+    if ((flags & GUI_INPUT_DEBUG_PLAYER) && state.getLocalPlayer())
+        state.getLocalPlayer()->printDebugInfo();
     
-    // dump debug info on stderr
-    if (flags & GUI_INPUT_DEBUG_PLAYER)
-        player->printDebugInfo();
-    
-    // build input_mask
-    input.readPlayerInput(input_mask, input_dt);
-    
-    // apply input if there was any
-    if (input_mask)
-        player->handleInput(input_mask, input_dt);
+    // toggle fullscreen?
+    if (flags & GUI_INPUT_TOGGLE_FULLSCREEN) {
+        if (is_fullscreen())
+            set_windowed();
+        else
+            set_fullscreen();
+    }
 }
 
 static PixelDimension value_between (PixelDimension low, PixelDimension value, PixelDimension high) {
@@ -114,10 +131,10 @@
 }
 
 void Graphics::draw_player_info(CL_GraphicContext *gc, Player *p) {
-    int box_top = GRAPHICS_RESOLUTION_HEIGHT - 100;
+    int box_top = resolution.y - 100;
     int box_left = 0;
-    int box_right = GRAPHICS_RESOLUTION_WIDTH;
-    int box_bottom = GRAPHICS_RESOLUTION_HEIGHT;
+    int box_right = resolution.x;
+    int box_bottom = resolution.y;
     int bar_length = 3; // *100
 
     // draw status info at bottom of display
--- a/src/Graphics.hh	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Graphics.hh	Tue Jan 13 20:17:03 2009 +0200
@@ -37,12 +37,24 @@
     CL_Font simple_font;
 
 public:
-    Graphics (Engine &engine, GameState &state);
+    Graphics (Engine &engine, GameState &state, PixelCoordinate resolution, bool fullscreen);
 
     CL_Font& getSimpleFont (void) { return simple_font; }
+
+    static const std::vector<CL_DisplayMode> & getDisplayModes (void);
     
 private:
+    /**
+     * Reads current input events from Input and applies them, using LocalPlayer::handleInput and
+     * Graphics::handle_input.
+     */
     void check_input (void);
+    
+    /**
+     * Handles GuiInput flags read from Input.
+     */
+    void handle_input (GuiInput flags);
+
     void do_redraw (void);
     
     void on_update (TimeMS tick_length);
--- a/src/Input.cc	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Input.cc	Tue Jan 13 20:17:03 2009 +0200
@@ -22,10 +22,11 @@
 };
 
 InputKeymapEntry<GuiInputBit> INPUT_GUI_KEYMAP[] = {
-    {   GUI_INPUT_QUIT,             0,              { CL_KEY_ESCAPE,    0               } },
-    {   GUI_INPUT_DISPLAY_WEAPON,   0,              { CL_KEY_ENTER,     0               } },
-    {   GUI_INPUT_DEBUG_PLAYER,     0,              { CL_KEY_I,         0               } },
-    {   GUI_INPUT_NONE,             0,              { 0,                0,              } }
+    {   GUI_INPUT_QUIT,                 0,                  { CL_KEY_ESCAPE,    0               } },
+    {   GUI_INPUT_DISPLAY_WEAPON,       0,                  { CL_KEY_ENTER,     0               } },
+    {   GUI_INPUT_DEBUG_PLAYER,         0,                  { CL_KEY_I,         0               } },
+    {   GUI_INPUT_TOGGLE_FULLSCREEN,    INPUT_FLAG_NOREPEAT,{ CL_KEY_LCONTROL,  CL_KEY_F        } },
+    {   GUI_INPUT_NONE,                 0,                  { 0,                0,              } }
 };
 
 /*
--- a/src/Input.hh	Tue Jan 13 16:11:37 2009 +0000
+++ b/src/Input.hh	Tue Jan 13 20:17:03 2009 +0200
@@ -68,6 +68,8 @@
     GUI_INPUT_QUIT              = 0x0001,
     GUI_INPUT_DISPLAY_WEAPON    = 0x0002,
     GUI_INPUT_DEBUG_PLAYER      = 0x0004,
+
+    GUI_INPUT_TOGGLE_FULLSCREEN = 0x0008,
 };
 
 /**