diff options
39 files changed, 392 insertions, 200 deletions
diff --git a/src/game.cpp b/src/game.cpp index adad9e0f..71340f16 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -101,10 +101,6 @@ void second(void) { } END_OF_FUNCTION(second); -/** - * Return elapsed time (Warning: very unsafe function. It supposes the delay - * is always < MAX_TIME ms) - */ short get_elapsed_time(short start_time) { if (start_time <= tick_time) { return tick_time - start_time; @@ -114,9 +110,6 @@ short get_elapsed_time(short start_time) { } } -/** - * Main game loop - */ void game() { do_init(); GraphicEngine *graphicEngine = new GraphicEngine(); @@ -146,9 +139,6 @@ void game() { close_session(); } -/** - * Initialize game engine - */ void do_init() { if (!load_map(map_path)) { error("Could not find map file"); @@ -188,15 +178,9 @@ void do_init() { remove("./docs/packet.list"); } -/** - * Clean the engine - */ void do_exit() { } -/** - * Check user input - */ void do_input() { if (walk_status == 0) { int x = get_x(player_node->coordinates); @@ -354,18 +338,12 @@ bool handle_key(int unicode, int scancode) return false; } -/** - * Calculate packet length - */ int get_packet_length(short id) { int len = get_length(id); if (len == -1)len = RFIFOW(2); return len; } -/** - * Parse data received from map server into input buffer - */ void do_parse() { unsigned short id; char *temp; @@ -665,7 +643,7 @@ void do_parse() { } statusWindow->update(); if(char_info->hp==0) { - OkDialog *death = new OkDialog(guiTop, + OkDialog *death = new OkDialog("Message", "You're now dead, press ok to restart"); alert("","","","","",0,0); WFIFOW(0) = net_w_value(0x00b2); @@ -77,18 +77,40 @@ extern int server_tick; */ bool handle_key(int unicode, int scancode); +/** + * Main game loop + */ void game(); + +/** + * Initialize game engine + */ void do_init(); + +/** + * Check user input + */ void do_input(); + +/** + * Parse data received from map server into input buffer + */ void do_parse(); -void do_graphic(); -void do_logic(); + +/** + * Clean the engine + */ void do_exit(); -int get_packet_length(short); -char get_x_offset(char, char); -char get_y_offset(char, char); +/** + * Calculate packet length + */ +int get_packet_length(short); +/** + * Returns elapsed time. (Warning: very unsafe function, it supposes the delay + * is always < 10 seconds) + */ short get_elapsed_time(short start_time); #endif diff --git a/src/graphic/graphic.cpp b/src/graphic/graphic.cpp index 3b9e1e1e..0e5b9a32 100644 --- a/src/graphic/graphic.cpp +++ b/src/graphic/graphic.cpp @@ -158,29 +158,29 @@ GraphicEngine::GraphicEngine() { // Create dialogs - statusWindow = new StatusWindow(guiTop); + statusWindow = new StatusWindow(); statusWindow->setPosition(SCREEN_W - statusWindow->getWidth() - 10, 10); - buyDialog = new BuyDialog(guiTop); + buyDialog = new BuyDialog(); buyDialog->setVisible(false); - sellDialog = new SellDialog(guiTop); + sellDialog = new SellDialog(); sellDialog->setVisible(false); - buySellDialog = new BuySellDialog(guiTop, new BuySellListener()); + buySellDialog = new BuySellDialog(new BuySellListener()); buySellDialog->setVisible(false); - inventoryWindow = new InventoryWindow(guiTop); + inventoryWindow = new InventoryWindow(); inventoryWindow->setVisible(false); inventoryWindow->setPosition(100, 100); - npcTextDialog = new NpcTextDialog(guiTop); + npcTextDialog = new NpcTextDialog(); npcTextDialog->setVisible(false); - npcListDialog = new NpcListDialog(guiTop); + npcListDialog = new NpcListDialog(); npcListDialog->setVisible(false); - skillDialog = new SkillDialog(guiTop); + skillDialog = new SkillDialog(); skillDialog->setVisible(false); // Give focus to the chat input diff --git a/src/graphic/graphic.h b/src/graphic/graphic.h index ea9b71f0..ed62bf79 100644 --- a/src/graphic/graphic.h +++ b/src/graphic/graphic.h @@ -65,6 +65,9 @@ extern NpcListDialog *npcListDialog; extern NpcTextDialog *npcTextDialog; extern SkillDialog *skillDialog; +char get_x_offset(char, char); +char get_y_offset(char, char); + /** * The action listener for the chat field. */ diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 8eefa503..ca76b40f 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -29,8 +29,8 @@ #include <sstream> -BuyDialog::BuyDialog(gcn::Container *parent): - Window(parent, "Buy"), +BuyDialog::BuyDialog(): + Window("Buy"), money(0) { itemList = new ListBox(this); diff --git a/src/gui/buy.h b/src/gui/buy.h index c58f5248..7a6bd484 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -44,7 +44,7 @@ class BuyDialog : public Window, public gcn::ActionListener, * * @see Window::Window */ - BuyDialog(gcn::Container *parent); + BuyDialog(); /** * Destructor. diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index eae19917..d522e6f2 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -24,8 +24,8 @@ #include "buysell.h" #include "button.h" -BuySellDialog::BuySellDialog(gcn::Container *parent, gcn::ActionListener *al): - Window(parent, "Shop") +BuySellDialog::BuySellDialog(gcn::ActionListener *al): + Window("Shop") { buyButton = new Button("Buy"); sellButton = new Button("Sell"); diff --git a/src/gui/buysell.h b/src/gui/buysell.h index 5289f649..02ddb816 100644 --- a/src/gui/buysell.h +++ b/src/gui/buysell.h @@ -40,7 +40,7 @@ class BuySellDialog : public Window { * * @see Window::Window */ - BuySellDialog(gcn::Container *parent, gcn::ActionListener *al); + BuySellDialog(gcn::ActionListener *al); /** * Destructor. diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 537a33ad..d54b8ca7 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -23,11 +23,13 @@ #include "char_select.h" #include "textfield.h" +#include "button.h" +#include "ok_dialog.h" #include "../graphic/graphic.h" #include "../main.h" -CharSelectDialog::CharSelectDialog(gcn::Container *parent) - : Window(parent, "Select Character") +CharSelectDialog::CharSelectDialog(): + Window("Select Character") { selectButton = new Button(" OK "); cancelButton = new Button("Cancel"); @@ -112,8 +114,8 @@ int curHairColor = 0; int curHairStyle = 0; std::string curName; -CharCreateDialog::CharCreateDialog(gcn::Container *parent) - : Window(parent, "Create Character") +CharCreateDialog::CharCreateDialog(): + Window("Create Character") { nameField = new TextField(""); nameLabel = new gcn::Label("Name:"); @@ -208,7 +210,7 @@ void CharCreateDialog::action(const std::string& eventId) void charSelect() { CharSelectDialog *sel; - sel = new CharSelectDialog(guiTop); + sel = new CharSelectDialog(); state = LOGIN; @@ -306,7 +308,7 @@ void serverCharSelect() void charCreate() { - CharCreateDialog *create = new CharCreateDialog(guiTop); + CharCreateDialog *create = new CharCreateDialog(); state = LOGIN; while (!key[KEY_ESC] && !key[KEY_ENTER] && state != EXIT && @@ -344,7 +346,7 @@ void charCreate() void serverCharDelete() { state = CHAR_SELECT; // Delete a character - if (yes_no("Confirm", "Are you sure?")==0) { + if (yes_no("Confirm", "Are you sure?") == 0) { // Request character deletion WFIFOW(0) = net_w_value(0x0068); WFIFOL(2) = net_l_value(char_info->id); @@ -353,10 +355,11 @@ void serverCharDelete() { while ((in_size < 2) || (out_size > 0)) flush(); if (RFIFOW(0) == 0x006f) { RFIFOSKIP(2); - ok("Info", "Player deleted"); free(char_info); n_character = 0; - } else if (RFIFOW(0) == 0x006c) { + ok("Info", "Player deleted"); + } + else if (RFIFOW(0) == 0x006c) { switch (RFIFOB(2)) { case 0: ok("Error", "Access denied"); @@ -366,7 +369,10 @@ void serverCharDelete() { break; } RFIFOSKIP(3); - } else ok("Error", "Unknown error"); + } + else { + ok("Error", "Unknown error"); + } } } diff --git a/src/gui/char_select.h b/src/gui/char_select.h index ef643725..475deab0 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -29,7 +29,6 @@ #include "../main.h" #include "../net/network.h" #include "gui.h" -#include "button.h" #include <guichan/allegro.hpp> /** @@ -39,10 +38,10 @@ */ class CharSelectDialog : public Window, public gcn::ActionListener { private: - Button *selectButton; - Button *cancelButton; - Button *newCharButton; - Button *delCharButton; + gcn::Button *selectButton; + gcn::Button *cancelButton; + gcn::Button *newCharButton; + gcn::Button *delCharButton; gcn::Label *nameLabel; gcn::Label *levelLabel; @@ -50,22 +49,33 @@ class CharSelectDialog : public Window, public gcn::ActionListener { gcn::Label *moneyLabel; public: - CharSelectDialog(gcn::Container *parent); + /** + * Constructor. + */ + CharSelectDialog(); + + /** + * Destructor. + */ ~CharSelectDialog(); void action(const std::string& eventId); + void setName(const std::string name) { nameLabel->setCaption(name); } + void setLevel(const std::string level) { levelLabel->setCaption(level); } + void setJobLevel(const std::string level) { jobLevelLabel->setCaption(level); } + void setMoney(const std::string money) { moneyLabel->setCaption(money); @@ -81,21 +91,31 @@ class CharCreateDialog : public Window, public gcn::ActionListener { private: gcn::TextField *nameField; gcn::Label *nameLabel; - Button *nextHairColorButton; - Button *prevHairColorButton; + gcn::Button *nextHairColorButton; + gcn::Button *prevHairColorButton; gcn::Label *hairColorLabel; - Button *nextHairStyleButton; - Button *prevHairStyleButton; + gcn::Button *nextHairStyleButton; + gcn::Button *prevHairStyleButton; gcn::Label *hairStyleLabel; - Button *createButton; + gcn::Button *createButton; public: - CharCreateDialog(gcn::Container *parent); + /** + * Constructor. + */ + CharCreateDialog(); + + /** + * Destructor. + */ ~CharCreateDialog(); void action(const std::string& eventId); - std::string getName() { return nameField->getText(); } + + std::string getName() { + return nameField->getText(); + } }; void charSelect(); diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp index 4543a829..b042a05a 100644 --- a/src/gui/char_server.cpp +++ b/src/gui/char_server.cpp @@ -27,13 +27,14 @@ #include "window.h" #include "scrollarea.h" #include "listbox.h" +#include "ok_dialog.h" char server[30]; int showServerList = 1; -ServerSelectDialog::ServerSelectDialog(gcn::Container *parent): - Window(parent, "Select Server") +ServerSelectDialog::ServerSelectDialog(): + Window("Select Server") { serverListModel = new ServerListModel(); serverList = new ListBox(serverListModel); @@ -110,7 +111,7 @@ std::string ServerListModel::getElementAt(int i) { void char_server() { - ServerSelectDialog *dialog = new ServerSelectDialog(guiTop); + ServerSelectDialog *dialog = new ServerSelectDialog(); state = LOGIN; @@ -132,7 +133,7 @@ void server_char_server(int serverIndex) { ret = open_session(iptostring(server_info[serverIndex].address), server_info[serverIndex].port); if (ret == SOCKET_ERROR) { - ok("Error", "Unable to connect to char server"); + new OkDialog("Error", "Unable to connect to char server"); return; } @@ -145,16 +146,16 @@ void server_char_server(int serverIndex) { WFIFOB(16) = net_b_value(sex); WFIFOSET(17); - while((in_size<4)||(out_size>0))flush(); + while ((in_size<4)||(out_size>0))flush(); RFIFOSKIP(4); - while(in_size<3)flush(); + while (in_size<3)flush(); - if(RFIFOW(0)==0x006b) { + if (RFIFOW(0)==0x006b) { while(in_size<RFIFOW(2))flush(); n_character = (RFIFOW(2)-24)/106; - char_info = (PLAYER_INFO *)malloc(sizeof(PLAYER_INFO)*n_character); - for(int i=0;i<n_character;i++) { + char_info = (PLAYER_INFO *)malloc(sizeof(PLAYER_INFO) * n_character); + for (int i = 0; i < n_character; i++) { char_info[i].id = RFIFOL(24+106*i); strcpy(char_info[i].name, RFIFOP(24+106*i+74)); char_info[i].hp = RFIFOW(24+106*i+42); @@ -183,20 +184,19 @@ void server_char_server(int serverIndex) { RFIFOSKIP(RFIFOW(2)); - } else if(RFIFOW(0)==0x006c) { - switch(RFIFOB(2)) { - case 0: - ok("Error", "Access denied"); - break; - case 1: - ok("Error", "Cannot use this ID"); - break; - default: - ok("Error", "Rejected from server"); - break; + } + else if (RFIFOW(0) == 0x006c) { + std::string errorStr; + switch (RFIFOB(2)) { + case 0: errorStr = "Access denied"; break; + case 1: errorStr = "Cannot use this ID"; break; + default: errorStr = "Rejected from server"; break; } + new OkDialog("Error", errorStr); RFIFOSKIP(3); close_session(); - } else ok("Error", "Unknown error"); + } else { + new OkDialog("Error", "Unknown error"); + } // Todo: add other packets } diff --git a/src/gui/char_server.h b/src/gui/char_server.h index 31c7c448..cc1bbe6b 100644 --- a/src/gui/char_server.h +++ b/src/gui/char_server.h @@ -59,7 +59,7 @@ class ServerSelectDialog : public Window, public gcn::ActionListener { * * @see Window::Window */ - ServerSelectDialog(gcn::Container *parent); + ServerSelectDialog(); /** * Destructor diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 5cd475af..dac21c00 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -28,6 +28,7 @@ #include "../log.h" #include "../sound/sound.h" #include "allegroinput.h" +#include "window.h" #include "windowcontainer.h" #define GUI_BMP_COUNT 11 @@ -49,9 +50,9 @@ DATAFILE *gui_gfx; // Guichan stuff -Gui* gui; -gcn::AllegroGraphics* guiGraphics; // Graphics driver -gcn::Container* guiTop; // The top container +Gui *gui; +gcn::AllegroGraphics *guiGraphics; // Graphics driver +WindowContainer *guiTop; // The top container Gui::Gui(BITMAP *screen) @@ -71,6 +72,7 @@ Gui::Gui(BITMAP *screen) guiTop = new WindowContainer(); guiTop->setDimension(gcn::Rectangle(0, 0, SCREEN_W, SCREEN_H)); guiTop->setOpaque(false); + Window::setWindowContainer(guiTop); // Create focus handler focusHandler = new gcn::FocusHandler(); diff --git a/src/gui/gui.h b/src/gui/gui.h index 1055db0b..e3a77f31 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -32,6 +32,7 @@ #include <guichan/allegro.hpp> #include <allegro.h> #include <string.h> +#include "windowcontainer.h" /** * \defgroup GUI GUI related classes @@ -163,7 +164,7 @@ extern LexSkin gui_skin; extern BITMAP *gui_bitmap; extern Gui* gui; -extern gcn::Container* guiTop; // The top container +extern WindowContainer* guiTop; // The top container extern gcn::AllegroGraphics* guiGraphics; // Graphics driver /** Initialize gui system */ diff --git a/src/gui/inventory.cpp b/src/gui/inventory.cpp index 8d75f34e..8662841e 100644 --- a/src/gui/inventory.cpp +++ b/src/gui/inventory.cpp @@ -24,8 +24,8 @@ #include "inventory.h" #include <sstream> -InventoryWindow::InventoryWindow(gcn::Container *parent): - Window(parent, "Inventory") +InventoryWindow::InventoryWindow(): + Window("Inventory") { setSize(322, 60); diff --git a/src/gui/inventory.h b/src/gui/inventory.h index 21ffe6bc..87a99b07 100644 --- a/src/gui/inventory.h +++ b/src/gui/inventory.h @@ -40,12 +40,11 @@ #define INVENTORY_SIZE 100 struct ITEM_HOLDER { // the holder of a item - int id; // the id of the item - int quantity; // number of items - //int index; // item position + int id; // the id of the item + int quantity; // number of items + //int index; // item position }; - /** * Inventory dialog. * @@ -53,7 +52,14 @@ struct ITEM_HOLDER { // the holder of a item */ class InventoryWindow : public Window { public: - InventoryWindow(gcn::Container *parent); + /** + * Constructor. + */ + InventoryWindow(); + + /** + * Destructor. + */ ~InventoryWindow(); /** @@ -77,7 +83,7 @@ class InventoryWindow : public Window { int changeQuantity(int index, int quantity); /** - * Increase quantity of an item + * Increase quantity of an item. */ int increaseQuantity(int index, int quantity); diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 00797917..08276562 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -27,10 +27,11 @@ #include "checkbox.h" #include "textfield.h" #include "passwordfield.h" +#include "ok_dialog.h" #include "../graphic/graphic.h" -LoginDialog::LoginDialog(gcn::Container *parent): - Window(parent, "Login") +LoginDialog::LoginDialog(): + Window("Login") { userLabel = new gcn::Label("Name:"); passLabel = new gcn::Label("Password:"); @@ -129,7 +130,7 @@ void LoginDialog::action(const std::string& eventId) void login() { - LoginDialog *dialog = new LoginDialog(guiTop); + LoginDialog *dialog = new LoginDialog(); while (state == LOGIN) { blit(login_wallpaper, buffer, 0, 0, 0, 0, 800, 600); @@ -181,17 +182,17 @@ void server_login(const std::string& user, const std::string& pass) { while (in_size < RFIFOW(2)) { flush(); } - n_server = (RFIFOW(2)-47)/32; - server_info = (SERVER_INFO*)malloc(sizeof(SERVER_INFO)*n_server); + n_server = (RFIFOW(2) - 47) / 32; + server_info = (SERVER_INFO*)malloc(sizeof(SERVER_INFO) * n_server); account_ID = RFIFOL(8); session_ID1 = RFIFOL(4); session_ID2 = RFIFOL(12); sex = RFIFOB(46); for (int i = 0; i < n_server; i++) { - server_info[i].address = RFIFOL(47+32*i); - memcpy(server_info[i].name, RFIFOP(47+32*i+6), 20); - server_info[i].online_users = RFIFOW(47+32*i+26); - server_info[i].port = RFIFOW(47+32*i+4); + server_info[i].address = RFIFOL(47 + 32 * i); + memcpy(server_info[i].name, RFIFOP(47 + 32 * i + 6), 20); + server_info[i].online_users = RFIFOW(47 + 32 * i + 26); + server_info[i].port = RFIFOW(47 + 32 * i + 4); state = CHAR_SERVER; } log("Network", "Server: %s (%s:%d)", server_info[0].name, @@ -203,17 +204,17 @@ void server_login(const std::string& user, const std::string& pass) { else if (RFIFOW(0) == 0x006a) { switch (RFIFOB(2)) { case 0: - ok("Error", "Unregistered ID"); + new OkDialog("Error", "Unregistered ID"); break; case 1: - ok("Error", "Wrong password"); + new OkDialog("Error", "Wrong password"); break; } state = LOGIN; RFIFOSKIP(23); } else { - ok("Error", "Unknown error"); + new OkDialog("Error", "Unknown error"); } // Todo: add other packets, also encrypted } diff --git a/src/gui/login.h b/src/gui/login.h index 3157a727..b133a2c5 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -52,7 +52,7 @@ class LoginDialog : public Window, public gcn::ActionListener { * * @see Window::Window */ - LoginDialog(gcn::Container *parent); + LoginDialog(); /** * Destructor diff --git a/src/gui/npc.cpp b/src/gui/npc.cpp index fbb55d65..73e1393a 100644 --- a/src/gui/npc.cpp +++ b/src/gui/npc.cpp @@ -27,8 +27,8 @@ #include "listbox.h" #include "../game.h" -NpcListDialog::NpcListDialog(gcn::Container *parent): - Window(parent, "NPC") +NpcListDialog::NpcListDialog(): + Window("NPC") { itemList = new ListBox(this); scrollArea = new ScrollArea(itemList); diff --git a/src/gui/npc.h b/src/gui/npc.h index d0810201..68d63c4f 100644 --- a/src/gui/npc.h +++ b/src/gui/npc.h @@ -43,7 +43,7 @@ class NpcListDialog : public Window, public gcn::ActionListener, * * @see Window::Window */ - NpcListDialog(gcn::Container *parent); + NpcListDialog(); /** * Destructor. diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index f86f45e9..27c28512 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -27,8 +27,8 @@ #include "textbox.h" #include "../game.h" -NpcTextDialog::NpcTextDialog(gcn::Container *parent): - Window(parent, "NPC") +NpcTextDialog::NpcTextDialog(): + Window("NPC") { textBox = new TextBox(); textBox->setEditable(false); diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index 6bb7d943..ed228931 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -42,7 +42,7 @@ class NpcTextDialog : public Window, public gcn::ActionListener * * @see Window::Window */ - NpcTextDialog(gcn::Container *parent); + NpcTextDialog(); /** * Destructor. diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp index b997cdb2..887c09f7 100644 --- a/src/gui/ok_dialog.cpp +++ b/src/gui/ok_dialog.cpp @@ -22,9 +22,10 @@ */ #include "ok_dialog.h" +#include "button.h" -OkDialog::OkDialog(gcn::Container *parent, std::string msg): - Window(parent, "Message") +OkDialog::OkDialog(const std::string& title, const std::string& msg): + Window(title, true) { userLabel = new gcn::Label(msg); okButton = new Button("OK"); @@ -52,5 +53,7 @@ OkDialog::~OkDialog() void OkDialog::action(const std::string& eventId) { if (eventId == "ok") { + //getParent()->remove(this); + windowContainer->scheduleDelete(this); } } diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h index cc04546b..ad0359b1 100644 --- a/src/gui/ok_dialog.h +++ b/src/gui/ok_dialog.h @@ -26,7 +26,6 @@ #include "gui.h" #include "window.h" -#include "button.h" /** * An 'Ok' button dialog. @@ -36,14 +35,14 @@ class OkDialog : public Window, public gcn::ActionListener { public: /** - * Constructor + * Constructor. * * @see Window::Window */ - OkDialog(gcn::Container *parent, std::string); + OkDialog(const std::string &title, const std::string &msg); /** - * Destructor + * Destructor. */ ~OkDialog(); diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index bdf6ec6d..d24daff3 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -30,8 +30,8 @@ #include <sstream> -SellDialog::SellDialog(gcn::Container *parent): - Window(parent, "Sell") +SellDialog::SellDialog(): + Window("Sell") { itemList = new ListBox(this); scrollArea = new ScrollArea(itemList); diff --git a/src/gui/sell.h b/src/gui/sell.h index 610d1aca..50da5a10 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -44,7 +44,7 @@ class SellDialog : public Window, public gcn::ActionListener, * * @see Window::Window */ - SellDialog(gcn::Container *parent); + SellDialog(); /** * Destructor. diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index d3a8e0ae..89f7e0a4 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -58,8 +58,8 @@ std::string ModeListModel::getElementAt(int i) { return modes[i].desc; } -Setup::Setup(gcn::Container *parent) - : Window(parent, "Setup") +Setup::Setup(): + Window("Setup") { modeListModel = new ModeListModel(); displayLabel = new gcn::Label("Display settings"); @@ -174,7 +174,7 @@ void Setup::action(const std::string& eventId) Setup *Setup::ptr = NULL; Setup *Setup::create_setup() { if (ptr == NULL) { - ptr = new Setup(guiTop); + ptr = new Setup(); } else { ptr->setVisible(true); diff --git a/src/gui/setup.h b/src/gui/setup.h index 7cb6c120..a1b00ea1 100644 --- a/src/gui/setup.h +++ b/src/gui/setup.h @@ -72,7 +72,7 @@ class Setup : public Window, public gcn::ActionListener { /** * Constructor. */ - Setup(gcn::Container *parent); + Setup(); /** * Destructor. diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 2139c4ff..b66a5426 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -24,6 +24,7 @@ #include "skill.h" #include "listbox.h" #include "scrollarea.h" +#include "button.h" extern PLAYER_INFO *char_info; @@ -112,8 +113,8 @@ void SkillListModel::setSkill(int id, int lv, int sp) } -SkillDialog::SkillDialog(gcn::Container *parent) - : Window(parent, "Skills") +SkillDialog::SkillDialog(): + Window("Skills") { skills = new SkillListModel(); skillListBox = new ListBox(skills); diff --git a/src/gui/skill.h b/src/gui/skill.h index 78f48e30..0b0f737b 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -25,7 +25,6 @@ #define _TMW_SKILL_H #include <allegro.h> -#include "button.h" #include "../main.h" struct SKILL { @@ -40,9 +39,18 @@ struct SKILL { */ class SkillListModel : public gcn::ListModel { - std::vector<SKILL*> skillList; + private: + std::vector<SKILL*> skillList; + public: + /** + * Constructor. + */ SkillListModel(); + + /** + * Destructor. + */ virtual ~SkillListModel(); int getNumberOfElements(); @@ -66,11 +74,18 @@ class SkillDialog : public Window, public gcn::ActionListener SkillListModel *skills; gcn::Label *pointsLabel; - Button *incButton; - Button *closeButton; + gcn::Button *incButton; + gcn::Button *closeButton; public: - SkillDialog(gcn::Container *); + /** + * Constructor. + */ + SkillDialog(); + + /** + * Destructor. + */ ~SkillDialog(); void action(const std::string&); diff --git a/src/gui/stats.cpp b/src/gui/stats.cpp index eebfab70..d8ea9c34 100644 --- a/src/gui/stats.cpp +++ b/src/gui/stats.cpp @@ -25,8 +25,8 @@ extern PLAYER_INFO *char_info; -StatsWindow::StatsWindow(gcn::Container *parent) - : Window(parent, "Stats") +StatsWindow::StatsWindow(): + Window("Stats") { // New labels for (i = 0; i < 6; i++) { @@ -91,7 +91,7 @@ StatsWindow::~StatsWindow() { StatsWindow * StatsWindow::ptr = NULL; StatsWindow * StatsWindow::create_statswindow() { if (ptr == NULL) { - ptr = new StatsWindow(guiTop); + ptr = new StatsWindow(); } else { ptr->setVisible(true); diff --git a/src/gui/stats.h b/src/gui/stats.h index b1844e91..95ee235e 100644 --- a/src/gui/stats.h +++ b/src/gui/stats.h @@ -69,7 +69,7 @@ class StatsWindow : public Window, public gcn::ActionListener { /** * Constructor. */ - StatsWindow(gcn::Container *parent); + StatsWindow(); /** * Destructor. diff --git a/src/gui/status.cpp b/src/gui/status.cpp index 454b42b3..21a3c4a7 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -23,8 +23,8 @@ #include "status.h" -StatusWindow::StatusWindow(gcn::Container *parent): - Window(parent, "%s Lvl: % 2i Job: % 2i") +StatusWindow::StatusWindow(): + Window("%s Lvl: % 2i Job: % 2i") { hp = new gcn::Label("HP"); sp = new gcn::Label("SP"); diff --git a/src/gui/status.h b/src/gui/status.h index bf5758bf..77cea322 100644 --- a/src/gui/status.h +++ b/src/gui/status.h @@ -41,7 +41,14 @@ */ class StatusWindow : public Window { public: - StatusWindow(gcn::Container *parent); + /** + * Constructor. + */ + StatusWindow(); + + /** + * Destructor. + */ ~StatusWindow(); /** diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 52665213..19621c07 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -25,7 +25,9 @@ #include "gui.h" #include <guichan/allegro.hpp> -Window::Window(gcn::Container *parent, const std::string& text) : +WindowContainer *Window::windowContainer = NULL; + +Window::Window(const std::string& text, bool modal): caption(text), mousePX(0), mousePY(0), @@ -53,8 +55,13 @@ Window::Window(gcn::Container *parent, const std::string& text) : chrome->setY(titlebarHeight); gcn::Container::add(chrome); - // Add this window to the parent container - parent->add(this); + // Add this window to the window container + if (windowContainer) { + windowContainer->add(this, modal); + } + else { + throw GCN_EXCEPTION("Window::Window. no windowContainer set"); + } } Window::~Window() @@ -67,6 +74,11 @@ Window::~Window() delete chrome; } +void Window::setWindowContainer(WindowContainer *wc) +{ + windowContainer = wc; +} + void Window::draw(gcn::Graphics* graphics) { // Draw container background when opaque diff --git a/src/gui/window.h b/src/gui/window.h index 0a0170d8..b80a14c1 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -27,6 +27,7 @@ #include <iostream> #include <allegro.h> #include <guichan.hpp> +#include "windowcontainer.h" /** * A window. This window can be dragged around and has a title bar. @@ -35,7 +36,7 @@ */ class Window : public gcn::Container, public gcn::MouseListener { - private: + protected: gcn::Container *chrome; /**< Contained container */ std::string caption; /**< Title bar caption */ int z; /**< Z position of the window */ @@ -50,21 +51,28 @@ class Window : public gcn::Container, public gcn::MouseListener BITMAP *dMid; /**< Middle of title bar */ BITMAP *dRight; /**< Right side of title bar */ + /** The window container windows add themselves to. */ + static WindowContainer* windowContainer; + public: /** * Constructor. Initializes the title to the given text and hooks - * itself into the given parent. + * itself into the window container. * - * @param parent The parent container to which this window will add - * itself. * @param text The initial window title, "Window" by default. + * @param modal Block input to other windows. */ - Window(gcn::Container *parent, const std::string& text = "Window"); + Window(const std::string& text = "Window", bool modal = false); /** * Destructor. */ - ~Window(); + virtual ~Window(); + + /** + * Sets the window container to be used by new windows. + */ + static void setWindowContainer(WindowContainer *windowContainer); /** * Draws the window. diff --git a/src/gui/windowcontainer.cpp b/src/gui/windowcontainer.cpp index 460b99e5..c9ce6eff 100644 --- a/src/gui/windowcontainer.cpp +++ b/src/gui/windowcontainer.cpp @@ -21,14 +21,26 @@ * $Id$ */ +#include <iostream> #include "windowcontainer.h" WindowContainer::WindowContainer(): - gcn::Container(), - mouseDown(false) + mouseDown(false), + modalWidget(NULL) { } +void WindowContainer::logic() +{ + std::list<gcn::Widget*>::iterator i = deathList.begin(); + while (i != deathList.end()) { + delete (*i); + i = deathList.erase(i); + } + + gcn::Container::logic(); +} + void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput) { if (mouseInput.getType() == gcn::MouseInput::PRESS) @@ -40,19 +52,18 @@ void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput) mouseDown = false; } - /* - * Make drag events not change widget with mouse. The Window instances - * need this behaviour to be able to handle window dragging. - */ + // Make drag events not change widget with mouse. The Window instances + // need this behaviour to be able to handle window dragging. if (!(mouseInput.getType() == gcn::MouseInput::MOTION && mouseDown)) { Widget* tempWidgetWithMouse = NULL; - WidgetIterator iter; + WidgetIterator iter; for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++) { if ((*iter)->getDimension().isPointInRect( - mouseInput.x, mouseInput.y) && (*iter)->isVisible()) + mouseInput.x, mouseInput.y) && + (*iter)->isVisible()) { tempWidgetWithMouse = (*iter); } @@ -72,7 +83,8 @@ void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput) } } - if (mWidgetWithMouse && !mWidgetWithMouse->hasFocus()) { + if (mWidgetWithMouse && !mWidgetWithMouse->hasFocus() && + (!modalWidget || modalWidget == mWidgetWithMouse)) { gcn::MouseInput mi = mouseInput; mi.x -= mWidgetWithMouse->getX(); mi.y -= mWidgetWithMouse->getY(); @@ -83,3 +95,48 @@ void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput) gcn::Widget::_mouseInputMessage(mouseInput); } } + +void WindowContainer::add(gcn::Widget *widget, bool modal) +{ + gcn::Container::add(widget); + if (modal) { + setModalWidget(widget); + } +} + +void WindowContainer::remove(gcn::Widget *widget) +{ + if (modalWidget == widget) { + modalWidget = NULL; + } + gcn::Container::remove(widget); +} + +void WindowContainer::_announceDeath(gcn::Widget *widget) +{ + if (modalWidget == widget) { + modalWidget = NULL; + } + gcn::Container::_announceDeath(widget); +} + +void WindowContainer::clear() +{ + modalWidget = NULL; + gcn::Container::clear(); +} + +void WindowContainer::setModalWidget(gcn::Widget *widget) +{ + modalWidget = widget; +} + +gcn::Widget *WindowContainer::getModalWidget() +{ + return modalWidget; +} + +void WindowContainer::scheduleDelete(gcn::Widget *widget) +{ + deathList.push_back(widget); +} diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h index e74b1831..8b5753a5 100644 --- a/src/gui/windowcontainer.h +++ b/src/gui/windowcontainer.h @@ -39,13 +39,64 @@ class WindowContainer : public gcn::Container { WindowContainer(); /** + * Do GUI logic. This functions adds automatic deletion of objects that + * volunteered to be deleted. + */ + void logic(); + + /** * Handles mouse input messages. Differs from standard behaviour in * that widget with mouse doesn't change while a button is pressed. */ void _mouseInputMessage(const gcn::MouseInput &mouseInput); + /** + * Adds a widget. The widget can be set to be modal, which will ensure + * only that widget will receive input. + */ + void add(gcn::Widget *widget, bool modal = false); + + /** + * Removes a widget. + */ + void remove(gcn::Widget *widget); + + /** + * This function is called by the containers children when they get + * destroyed. + */ + void _announceDeath(gcn::Widget *widget); + + /** + * Clears the container of all widgets. + */ + void clear(); + + /** + * Sets the modal widget. This will ensure only this widget will + * receive mouse or keyboard input events. + * + * @see Window::Window + */ + void setModalWidget(gcn::Widget *widget); + + /** + * Returns the current modal widget, or <code>NULL</code> if there + * is none. + */ + gcn::Widget *getModalWidget(); + + /** + * Schedule a widget for deletion. It will be deleted at the start of + * the next logic update. + */ + void scheduleDelete(gcn::Widget *widget); + protected: bool mouseDown; + gcn::Widget *modalWidget; + + std::list<gcn::Widget*> deathList; }; #endif diff --git a/src/main.cpp b/src/main.cpp index a955ea01..625b385d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -294,22 +294,8 @@ void init_engine() { // TODO: Remove Allegro config file usage from GUI look init_gui(buffer, "data/Skin/aqua.skin"); state = LOGIN; -} -/** Clear the engine */ -void exit_engine() { - config.write(dir); - delete dir; - gui_exit(); - destroy_bitmap(buffer); - allegro_exit(); -} - -/** Main */ -int main() { - init_engine(); #ifndef WIN32 - // initialize sound-engine and start playing intro-theme /-kth5 try { if (config.getValue("sound", 0) == 1) { @@ -328,33 +314,47 @@ int main() { warning(err); } #endif /* not WIN32 */ +} + +/** Clear the engine */ +void exit_engine() { + config.write(dir); + delete dir; + gui_exit(); + destroy_bitmap(buffer); + allegro_exit(); +} + +/** Main */ +int main() { + init_engine(); while (state != EXIT) { - switch(state) { - case LOGIN: - status("LOGIN"); - login(); - break; - case CHAR_SERVER: - status("CHAR_SERVER"); - char_server(); - break; - case CHAR_SELECT: - status("CHAR_SELECT"); - charSelect(); - break; - case GAME: + switch (state) { + case LOGIN: + status("LOGIN"); + login(); + break; + case CHAR_SERVER: + status("CHAR_SERVER"); + char_server(); + break; + case CHAR_SELECT: + status("CHAR_SELECT"); + charSelect(); + break; + case GAME: #ifndef WIN32 - sound.stopBgm(); + sound.stopBgm(); #endif /* not WIN32 */ - status("GAME"); - map_start(); - if( state==GAME ) - game(); - break; - default: - state = EXIT; - break; + status("GAME"); + map_start(); + if (state == GAME) + game(); + break; + default: + state = EXIT; + break; } } status("EXIT"); |