///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004-2007 by The Allacrost Project
// All Rights Reserved
//
// This code is licensed under the GNU GPL version 2. It is free software
// and you may modify it and/or redistribute it under the terms of this license.
// See http://www.gnu.org/copyleft/gpl.html for details.
///////////////////////////////////////////////////////////////////////////////
/** ****************************************************************************
*** \file menu_window.h
*** \author Raj Sharma, roos@allacrost.org
*** \brief Header file for menu window class
*** ***************************************************************************/
#ifndef __MENU_WINDOW_HEADER__
#define __MENU_WINDOW_HEADER__
#include "defs.h"
#include "utils.h"
#include "gui.h"
#include "screen_rect.h"
#include "image.h"
namespace hoa_video {
//! \brief How many milliseconds it takes for a window to scroll in or out of view.
const int32 VIDEO_MENU_SCROLL_TIME = 200;
/** \name Menu Edge Bitflags
*** \brief These flags control the presence/absence of each edge of the menu window.
*** For example, if you want to show a menu with its left edge hidden, then you would pass in all
*** the flags except VIDEO_MENU_EDGE_LEFT to the MenuWindow#Create() function, or alternatively
*** you could pass the complement of that bit flag (~VIDEO_MENU_EDGE_LEFT).
**/
//@{
const int32 VIDEO_MENU_EDGE_LEFT = 0x1;
const int32 VIDEO_MENU_EDGE_RIGHT = 0x2;
const int32 VIDEO_MENU_EDGE_TOP = 0x4;
const int32 VIDEO_MENU_EDGE_BOTTOM = 0x8;
const int32 VIDEO_MENU_EDGE_ALL = 0xF;
//@}
/** \brief Menu display modes control how the menu window appears or disappears.
*** The specific display modes include:
*** - VIDEO_MENU_INSTANT: appears/disappears instantly
*** - VIDEO_MENU_EXPAND_FROM_CENTER: starts as a thin horizontal line at center and expands out
**/
enum VIDEO_MENU_DISPLAY_MODE {
VIDEO_MENU_INVALID = -1,
VIDEO_MENU_INSTANT = 0,
VIDEO_MENU_EXPAND_FROM_CENTER = 1,
VIDEO_MENU_TOTAL = 2
};
/** \brief These enums are used to tell the visiblity state of a menu window.
*** The possible states and their meaning include:
*** - VIDEO_MENU_STATE_SHOWN: the menu is fully shown
*** - VIDEO_MENU_STATE_SHOWING: the menu is still in the process of scrolling on to the screen
*** - VIDEO_MENU_STATE_HIDING: the menu is scrolling out of view, but is not completely hidden yet
*** - VIDEO_MENU_STATE_HIDDEN: the menu is fully hidden
**/
enum VIDEO_MENU_STATE {
VIDEO_MENU_STATE_INVALID = -1,
VIDEO_MENU_STATE_SHOWN = 0,
VIDEO_MENU_STATE_SHOWING = 1,
VIDEO_MENU_STATE_HIDING = 2,
VIDEO_MENU_STATE_HIDDEN = 3,
VIDEO_MENU_STATE_TOTAL = 4
};
namespace private_video {
/** ****************************************************************************
*** \brief A container class for a menu skin, consisting of border images and an interior
***
*** The GUISupervisor class manages all MenuSkins which have been loaded by the user.
*** Multiple menu skins may co-exist at one time and be drawn to the screen. The MenuWindow
*** class makes extensive use of MenuSkins.
***
*** \note The contructor and destructor of this class do nothing. The creation and destruction
*** of the images contained by this class is done from the GUI class.
***
*** \todo Add support for menu skin backgrounds to be tiled images versus
*** stretched images.
***
*** \todo Add support to allow menu skin backgrounds to be colors instead of
*** images.
*** ***************************************************************************/
class MenuSkin {
public:
/** \brief A 2d array that holds the border images for the menu skin
*** The entries in this array represent the following parts:
*** - borders[0][0]: upper left corner
*** - borders[0][1]: top side
*** - borders[0][2]: upper right corner
*** - borders[1][0]: left side
*** - borders[1][1]: center (this is not an actual image, but rather contains the background colors for the four corners)
*** - borders[1][2]: right side
*** - borders[2][0]: bottom left corner
*** - borders[2][1]: bottom side
*** - borders[2][2]: bottom right corner
**/
StillImage borders[3][3];
/** \brief Border-connecting images, used when two or more MenuWindows are side by side.
*** There are four tri-connectors and one quad-connector. tri_t would be an image for
*** a 3-way connector on the top of a MenuWindow.
*** - connectors[0]: top tri-connector
*** - connectors[1]: bottom tri-connector
*** - connectors[2]: left tri-connector
*** - connectors[3]: right tri-connector
*** - connectors[4]: quad connector
**/
StillImage connectors[5];
//! \brief The (optional) background image of the menu skin that fills the inside of the MenuWindow
StillImage background;
MenuSkin()
{}
~MenuSkin()
{}
}; // class MenuSkin
} // namespace private_video
/** ****************************************************************************
*** \brief Represents GUI menu windows and handles their operation
***
*** A menu window is simply a rectangle drawn on the screen that has a border
*** image and a background. Menu windows exist to provide a base upon which to
*** draw text and images that are not a part of the regular game environment.
***
*** \todo Allow the user to specify an arbitrary amount of time for showing/
*** hiding the menu window.
*** ***************************************************************************/
class MenuWindow : public private_video::GUIElement {
friend class GUISupervisor;
public:
MenuWindow();
~MenuWindow()
{}
/** \brief Sets the width and height of the menu.
*** \param skin_name The name of the menu skin with which to construct this menu window.
*** \param w The window width in pixels, which must be within the range of [0.0f, 1024.f].
*** \param h The window height in pixels, which must be within the range of [0.0f, 768.f].
*** \param visible_flags A combination of bit flags, VIDEO_MENU_EDGE_LEFT, etc. that indicate
*** which edges are visible. A non-visible edge means that the border image gets stripped off.
*** \param shared_flags A combination of bitflags, VIDEO_MENU_EDGE_LEFT, etc. that tell which
*** edges are shared with other menus so they can use the appropriate connector images.
*** \return False and print an error message on failure. Otherwise return true upon success.
*** \note This function must be called before you attempt to draw the window.
**/
bool Create(std::string skin_name, float w, float h, int32 visible_flags = VIDEO_MENU_EDGE_ALL, int32 shared_flags = 0);
//! \note This version of the create function does not take a skin_name argument. It uses the default menu skin.
bool Create(float w, float h, int32 visible_flags = VIDEO_MENU_EDGE_ALL, int32 shared_flags = 0);
/** \brief You must call this method when you are finished using a menu.
*** Failure to neglect this call may result in problems like texture memory not being freed.
**/
void Destroy();
/** \brief Updates the menu window, used for gradual show/hide effects.
*** \param frame_time The time that has elapsed since the previous frame, in milliseconds.
**/
void Update(uint32 frame_time);
/** \brief This version is for the subclasses of menu window (allows us to use a single MenuWindow variable
*** to track the active window.
**/
virtual void Update()
{ }
//! \brief Draws the menu window to the screen.
void Draw();
/** \brief Causes the menu to begin making itself visible.
*** Depending on the display mode, the menu might show instantly or gradually.
*** You can check for when the menu is fully shown by checking if GetState()
*** returns VIDEO_MENU_STATE_SHOWN (until then, it is VIDEO_MENU_STATE_SHOWING).
*** \note The time it takes for the menu to show is VIDEO_MENU_SCROLL_TIME.
**/
void Show();
/** \brief Causes the menu to begin making itself not visible.
*** Depending on the display mode, the menu might hide instantly or gradually.
*** If it's gradual, you should still continue calling Draw() even after you call
*** Hide() until it's fully hidden. You can check if it's fully hidden by checking
*** if GetState() returns VIDEO_MENU_STATE_HIDDEN (until then, it will be
*** VIDEO_MENU_STATE_HIDING).
*** \note The time it takes for the menu to show is VIDEO_MENU_SCROLL_TIME
**/
void Hide();
/** \brief Does a self-check on all its members to see if all its members have been set to valid values.
*** \param &errors A reference to a string to be filled if any errors are found.
*** \return True if menu window is properly initialized, false if it is not.
***
*** This is used internally to make sure we have a valid object before doing any complicated operations.
*** If it detects any problems, it generates a list of errors and returns it by reference so they can be
*** displayed
**/
bool IsInitialized(std::string &errors);
/** \brief Changes the visible edge flags after the menu window has been created
*** \param flags Bit flags to specify which edges are visible and which are not.
*** \note This call is somewhat expensive since it has to recreate the menu window image.
**/
void ChangeEdgeVisibleFlags(int32 flags);
/** \brief Changes the shared edge flags after the menu window has been created
*** \param flags Bit flags to specify which edges are shared with other windows.
*** \note This call is somewhat expensive since it has to recreate the menu window image.
**/
void ChangeEdgeSharedFlags(int32 flags);
/** \brief Changes which menu skin is used by the window after it has been created
*** \param skin_name The name to which the skin is referred by
*** \note If the skin_name is invalid, a warning mesage will be printed and no change
*** will take place. This call is somewhat expensive since it has to recreate the menu window image.
**/
void ChangeMenuSkin(std::string& skin_name);
//! \name Class Member Access Functions
//@{
void SetDisplayMode(VIDEO_MENU_DISPLAY_MODE mode);
void GetDimensions(float &w, float &h) const
{ w = _width; h = _height; }
VIDEO_MENU_DISPLAY_MODE GetDisplayMode() const
{ return _display_mode; }
VIDEO_MENU_STATE GetState() const
{ return _window_state; }
ScreenRect GetScissorRect() const
{ return _scissor_rect; }
//@}
/** \brief Indicates whether the window is in the active context
*** \return True always here, subclasses can override to change the behaviour
**/
virtual bool IsActive()
{ return true; }
private:
//! \brief The current id of this object.
int32 _id;
//! \brief The dimensions of the menu window, in pixels.
float _width, _height;
//! \brief The dimensions of the space inside the window borders.
float _inner_width, _inner_height;
//! \brief Flags used to tell which edges of the menu window are visible.
int32 _edge_visible_flags;
//! \brief Flags used to tell which edges are shared with other windows.
int32 _edge_shared_flags;
//! \brief A pointer to the menu skin that the menu window currently uses
private_video::MenuSkin* _skin;
//! \brief The state of the menu window (hidden, shown, hiding, showing).
VIDEO_MENU_STATE _window_state;
//! \brief The number of milliseconds that have passed since the menu was shown.
int32 _display_timer;
//! \brief The image that creates the window
CompositeImage _menu_image;
//! \brief The window's display mode (instant, expand from center, etc).
VIDEO_MENU_DISPLAY_MODE _display_mode;
//! \brief Set to true if scissoring needs to be used on the window.
bool _is_scissored;
//! \brief The rectangle used for scissoring, set during each call to Update().
ScreenRect _scissor_rect;
/** \brief Used to create the menu window's image when the visible properties of the window change.
*** \return True if the menu image was successfully created, false otherwise.
***
*** \note This function may not create a window that is exactly the width and height requested.
*** It will automatically adjust the dimneions to minimalize warping. So for example, if the
*** border artwork is all 8x8 pixel images and you try to create a menu that is 117x69, it will get
*** rounded up to 120x72.
**/
bool _RecreateImage();
}; // class MenuWindow : public GUIElement
} // namespace hoa_video
#endif // __MENU_WINDOW_HEADER__