widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #01234
[Merge] lp:~widelands-dev/widelands/ui_improvments into lp:widelands
cghislai has proposed merging lp:~widelands-dev/widelands/ui_improvments into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #657285 in widelands: "Multiple tooltips may be shown when opening building information"
https://bugs.launchpad.net/widelands/+bug/657285
Bug #738643 in widelands: "Pause game while in 'save'-dialog"
https://bugs.launchpad.net/widelands/+bug/738643
Bug #738895 in widelands: "Show a message when the game is autosaving"
https://bugs.launchpad.net/widelands/+bug/738895
Bug #744749 in widelands: "Training sites should either show statistics as a military or as a productionsite"
https://bugs.launchpad.net/widelands/+bug/744749
Bug #763567 in widelands: "Sort Messages in Message Inbox to be most recent on top"
https://bugs.launchpad.net/widelands/+bug/763567
Bug #898129 in widelands: "Workarea color policy"
https://bugs.launchpad.net/widelands/+bug/898129
Bug #986526 in widelands: "Clarify "X player teams" map filter"
https://bugs.launchpad.net/widelands/+bug/986526
Bug #1132469 in widelands: "List of workers in building window not updating properly"
https://bugs.launchpad.net/widelands/+bug/1132469
Bug #1132476 in widelands: "change yellow color in white(?) - building menu % is unreadable"
https://bugs.launchpad.net/widelands/+bug/1132476
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ui_improvments/+merge/175090
Some fixes and features related to ui. See linked bugs and commit messages for details.
I tried to make commits as atomic as possible, so they could be merged separately if needed.
--
https://code.launchpad.net/~widelands-dev/widelands/ui_improvments/+merge/175090
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ui_improvments into lp:widelands.
=== added file 'pics/workarea12.png'
Binary files pics/workarea12.png 1970-01-01 00:00:00 +0000 and pics/workarea12.png 2013-07-16 17:39:34 +0000 differ
=== added file 'pics/workarea123.png'
Binary files pics/workarea123.png 1970-01-01 00:00:00 +0000 and pics/workarea123.png 2013-07-16 17:39:34 +0000 differ
=== removed file 'pics/workarea1cumulative.png'
Binary files pics/workarea1cumulative.png 2005-12-29 01:10:07 +0000 and pics/workarea1cumulative.png 1970-01-01 00:00:00 +0000 differ
=== added file 'pics/workarea23.png'
Binary files pics/workarea23.png 1970-01-01 00:00:00 +0000 and pics/workarea23.png 2013-07-16 17:39:34 +0000 differ
=== removed file 'pics/workarea2cumulative.png'
Binary files pics/workarea2cumulative.png 2005-12-29 01:10:07 +0000 and pics/workarea2cumulative.png 1970-01-01 00:00:00 +0000 differ
=== removed file 'pics/workarea3cumulative.png'
Binary files pics/workarea3cumulative.png 2009-11-09 19:01:11 +0000 and pics/workarea3cumulative.png 1970-01-01 00:00:00 +0000 differ
=== modified file 'src/chat.h'
--- src/chat.h 2013-02-10 19:36:24 +0000
+++ src/chat.h 2013-07-16 17:39:34 +0000
@@ -106,6 +106,12 @@
virtual void send(const std::string &) = 0;
/**
+ * Sends the given message to the local player only
+ * This may be used to display useful log messages.
+ */
+ virtual void send_local(const std::string &) = 0;
+
+ /**
* \return a (chronological) list of received chat messages.
* This list need not be stable or monotonic. In other words,
* subsequent calls to this functions may return a smaller or
=== modified file 'src/constants.h'
--- src/constants.h 2013-07-13 14:32:49 +0000
+++ src/constants.h 2013-07-16 17:39:34 +0000
@@ -131,7 +131,7 @@
* C++ is really bad at integer types. For example this constant is not
* recognized as a valid value of type Workarea_Info::size_type without a cast.
*/
-#define NUMBER_OF_WORKAREA_PICS static_cast<Workarea_Info::size_type>(3)
+#define NUMBER_OF_WORKAREA_PICS static_cast<Workarea_Info::size_type>(6)
/// The size of the transient (i.e. temporary) surfaces in the cache in bytes.
/// These are all surfaces that are not loaded from disk.
=== modified file 'src/debugconsole.cc'
--- src/debugconsole.cc 2013-02-10 19:36:24 +0000
+++ src/debugconsole.cc 2013-07-16 17:39:34 +0000
@@ -85,6 +85,10 @@
it->second(arg);
}
+ void send_local(const std::string& msg) {
+ send(msg);
+ }
+
const std::vector<ChatMessage> & getMessages() const
{
return messages;
=== modified file 'src/gamecontroller.cc'
--- src/gamecontroller.cc 2012-02-15 21:25:34 +0000
+++ src/gamecontroller.cc 2013-07-16 17:39:34 +0000
@@ -25,8 +25,10 @@
#include "logic/playercommand.h"
#include "profile/profile.h"
#include "wlapplication.h"
+#include "chat.h"
+#include "wui/interactive_player.h"
-struct SinglePlayerGameController : public GameController {
+struct SinglePlayerGameController : public GameController, public ChatProvider {
SinglePlayerGameController
(Widelands::Game &, bool useai, Widelands::Player_Number local);
~SinglePlayerGameController();
@@ -42,6 +44,10 @@
bool isPaused();
void setPaused(bool paused);
+ // Chat provider implementation
+ void send(const std::string & msg);
+ void send_local(const std::string & msg);
+ const std::vector<ChatMessage> & getMessages() const;
private:
Widelands::Game & m_game;
bool m_useai;
@@ -52,13 +58,14 @@
uint32_t m_player_cmdserial;
Widelands::Player_Number m_local;
std::vector<Computer_Player *> m_computerplayers;
+ std::vector<ChatMessage> m_chatmessages;
};
SinglePlayerGameController::SinglePlayerGameController
(Widelands::Game & game,
bool const useai,
Widelands::Player_Number const local)
- :
+ : ChatProvider(),
m_game (game),
m_useai (useai),
m_lastframe (WLApplication::get()->get_time()),
@@ -156,10 +163,31 @@
m_paused = paused;
}
+void SinglePlayerGameController::send_local(const std::string& msg)
+{
+ ChatMessage c;
+ c.msg = msg;
+ c.time = time(0);
+ m_chatmessages.push_back(c);
+ ChatProvider::send(c);
+}
+
+void SinglePlayerGameController::send(const std::string& msg)
+{
+ log("SinglePlayerGameController:: Cannot send chat messages in single player game!");
+}
+
+const std::vector< ChatMessage >& SinglePlayerGameController::getMessages() const
+{
+ return m_chatmessages;
+}
+
GameController * GameController::createSinglePlayer
(Widelands::Game & game,
bool const cpls,
Widelands::Player_Number const local)
{
- return new SinglePlayerGameController(game, cpls, local);
+ SinglePlayerGameController* spgc = new SinglePlayerGameController(game, cpls, local);
+ game.get_ipl()->set_chat_provider(*spgc);
+ return spgc;
}
=== modified file 'src/logic/building.cc'
--- src/logic/building.cc 2013-07-14 10:38:26 +0000
+++ src/logic/building.cc 2013-07-16 17:39:34 +0000
@@ -19,6 +19,7 @@
#include <cstdio>
#include <sstream>
+#include <boost/foreach.hpp>
#include "upcast.h"
#include "wexception.h"
@@ -436,6 +437,9 @@
}
PlayerImmovable::cleanup(egbase);
+
+ BOOST_FOREACH(boost::signals::connection& c, options_window_connections)
+ c.disconnect();
}
@@ -855,6 +859,7 @@
set_seeing(true);
}
PlayerImmovable::add_worker(worker);
+ workers_changed();
}
@@ -862,6 +867,7 @@
PlayerImmovable::remove_worker(worker);
if (not get_workers().size())
set_seeing(false);
+ workers_changed();
}
/**
=== modified file 'src/logic/building.h'
--- src/logic/building.h 2013-07-14 10:38:26 +0000
+++ src/logic/building.h 2013-07-16 17:39:34 +0000
@@ -34,6 +34,7 @@
#include <string>
#include <cstring>
#include <vector>
+#include <boost/signal.hpp>
namespace UI {class Window;}
struct BuildingHints;
@@ -223,6 +224,7 @@
void add_worker(Worker &);
void remove_worker(Worker &);
+ mutable boost::signal<void ()> workers_changed;
void send_message
(Game & game,
@@ -268,6 +270,9 @@
/// Whether we see our vision_range area based on workers in the building
bool m_seeing;
+
+ // Signals connected for the option window
+ std::vector<boost::signals::connection> options_window_connections;
};
}
=== modified file 'src/logic/production_program.cc'
--- src/logic/production_program.cc 2013-04-27 16:55:46 +0000
+++ src/logic/production_program.cc 2013-07-16 17:39:34 +0000
@@ -1288,7 +1288,7 @@
snprintf
(ps.m_result_buffer, sizeof(ps.m_result_buffer),
_("No soldier for this training level found!"));
- return ps.program_end(game, Failed);
+ return ps.program_end(game, Skipped);
}
if (attribute == atrHP) {
if ((*it)->get_hp_level() == level)
@@ -1378,7 +1378,7 @@
snprintf
(ps.m_result_buffer, sizeof(ps.m_result_buffer),
_("No soldier for this training level found!"));
- return ps.program_end(game, Failed);
+ return ps.program_end(game, Skipped);
}
if (attribute == atrHP) {
if ((*it)->get_hp_level () == level)
=== modified file 'src/logic/productionsite.cc'
--- src/logic/productionsite.cc 2013-05-25 09:30:35 +0000
+++ src/logic/productionsite.cc 2013-07-16 17:39:34 +0000
@@ -457,7 +457,6 @@
if (upcast(Game, game, &egbase))
try_start_working(*game);
-
return 0;
}
@@ -874,6 +873,7 @@
for (uint32_t i = descr().nr_working_positions(); i;)
m_working_positions[--i].worker->gain_experience(game);
m_result_buffer[0] = '\0';
+ Building::workers_changed();
}
calc_statistics();
break;
=== modified file 'src/logic/trainingsite.cc'
--- src/logic/trainingsite.cc 2013-06-16 16:29:48 +0000
+++ src/logic/trainingsite.cc 2013-07-16 17:39:34 +0000
@@ -192,12 +192,7 @@
*/
std::string TrainingSite::get_statistics_string()
{
- if (State * const state = get_state())
- return state->program->descname();
- else if (m_result == Completed)
- return _("Resting");
- else
- return _("Not Working");
+ return ProductionSite::get_statistics_string();
}
/**
=== modified file 'src/network/internet_gaming.cc'
--- src/network/internet_gaming.cc 2013-04-20 20:20:34 +0000
+++ src/network/internet_gaming.cc 2013-07-16 17:39:34 +0000
@@ -768,7 +768,14 @@
s.send(m_sock);
}
-
+void InternetGaming::send_local(const std::string& msg)
+{
+ ChatMessage c;
+ c.msg = msg;
+ c.time = time(0);
+ messages.push_back(c);
+ ChatProvider::send(c);
+}
/**
* \returns the boolean value of a string received from the metaserver.
=== modified file 'src/network/internet_gaming.h'
--- src/network/internet_gaming.h 2013-02-10 19:36:24 +0000
+++ src/network/internet_gaming.h 2013-07-16 17:39:34 +0000
@@ -114,6 +114,9 @@
// ChatProvider: sends a message via the metaserver.
void send(const std::string &);
+ // ChatProvider: sends local messages
+ void send_local(const std::string &);
+
/// ChatProvider: adds the message to the message list and calls parent.
void receive(const ChatMessage & msg) {messages.push_back(msg); ChatProvider::send(msg);}
=== modified file 'src/network/netclient.cc'
--- src/network/netclient.cc 2013-04-22 20:15:00 +0000
+++ src/network/netclient.cc 2013-07-16 17:39:34 +0000
@@ -628,6 +628,15 @@
s.send(d->sock);
}
+void NetClient::send_local(const std::string& msg)
+{
+ ChatMessage c;
+ c.msg = msg;
+ c.time = time(0);
+ d->chatmessages.push_back(c);
+ ChatProvider::send(c);
+}
+
const std::vector<ChatMessage> & NetClient::getMessages() const
{
return d->chatmessages;
=== modified file 'src/network/netclient.h'
--- src/network/netclient.h 2013-02-10 19:36:24 +0000
+++ src/network/netclient.h 2013-07-16 17:39:34 +0000
@@ -92,6 +92,7 @@
// ChatProvider interface
void send(const std::string & msg);
+ void send_local(const std::string & msg);
const std::vector<ChatMessage> & getMessages() const;
private:
=== modified file 'src/network/nethost.cc'
--- src/network/nethost.cc 2013-07-15 05:18:12 +0000
+++ src/network/nethost.cc 2013-07-16 17:39:34 +0000
@@ -498,6 +498,13 @@
h->send(c);
}
+ void send_local(const std::string & msg) {
+ ChatMessage c;
+ c.time = time(0);
+ c.msg = msg;
+ ChatProvider::send(c);
+ }
+
const std::vector<ChatMessage> & getMessages() const {
return messages;
}
=== modified file 'src/save_handler.cc'
--- src/save_handler.cc 2013-07-14 11:48:13 +0000
+++ src/save_handler.cc 2013-07-16 17:39:34 +0000
@@ -25,6 +25,8 @@
#include "io/filesystem/filesystem.h"
#include "game_io/game_saver.h"
#include "profile/profile.h"
+#include "wui/interactive_player.h"
+#include "chat.h"
#include "log.h"
@@ -51,7 +53,10 @@
if (elapsed < autosaveInterval)
return;
- log("Autosave: interval elapsed (%d s), saving\n", elapsed);
+ // TODO: defer saving to next tick so that this message is shown
+ // before the actual save, or put the saving logic in another thread
+ game.get_ipl()->get_chat_provider()->send_local
+ (_("Saving game..."));
// save the game
std::string complete_filename =
@@ -70,6 +75,8 @@
static std::string error;
if (!save_game(game, complete_filename, &error)) {
log("Autosave: ERROR! - %s\n", error.c_str());
+ game.get_ipl()->get_chat_provider()->send_local
+ (_("Saving failed!"));
// if backup file was created, move it back
if (backup_filename.length() > 0) {
@@ -88,6 +95,8 @@
}
log("Autosave: save took %d ms\n", m_last_saved_time - realtime);
+ game.get_ipl()->get_chat_provider()->send_local
+ (_("Game saved"));
}
/**
@@ -98,7 +107,6 @@
return;
m_last_saved_time = currenttime;
- log("Autosave: initialized\n");
m_initialized = true;
}
=== modified file 'src/timestring.cc'
--- src/timestring.cc 2013-03-21 10:45:51 +0000
+++ src/timestring.cc 2013-07-16 17:39:34 +0000
@@ -75,3 +75,18 @@
}
return timestring_buffer;
}
+
+char gamestringbuffer[] = "000:00:00";
+char * gametimestring(uint32_t gametime)
+{
+ uint32_t time = gametime / 1000;
+ gamestringbuffer[8] = '0' + time % 10;
+ gamestringbuffer[7] = '0' + (time /= 10) % 6;
+ gamestringbuffer[5] = '0' + (time /= 6) % 10;
+ gamestringbuffer[4] = '0' + (time /= 10) % 6;
+ gamestringbuffer[2] = '0' + (time /= 6) % 10;
+ gamestringbuffer[1] = '0' + (time /= 10) % 10;
+ gamestringbuffer[0] = '0' + (time /= 10);
+ return gamestringbuffer;
+}
+
=== modified file 'src/timestring.h'
--- src/timestring.h 2012-02-15 21:25:34 +0000
+++ src/timestring.h 2013-07-16 17:39:34 +0000
@@ -21,3 +21,8 @@
/// seconds since the Epoch). The return value points to a statically allocated
/// string which might be overwritten by subsequent calls.
char * timestring();
+
+/// Get a string representation of the game time
+/// as hhh:mm:ss. If Time represents more than
+/// 999 hours, it wraps around
+char * gametimestring(uint32_t gametime);
=== modified file 'src/ui_basic/progressbar.cc'
--- src/ui_basic/progressbar.cc 2012-02-15 21:25:34 +0000
+++ src/ui_basic/progressbar.cc 2013-07-16 17:39:34 +0000
@@ -21,10 +21,12 @@
#include "constants.h"
#include "graphic/font.h"
-#include "graphic/font_handler.h"
+#include "graphic/font_handler1.h"
+#include "text_layout.h"
#include "graphic/rendertarget.h"
#include <cstdio>
+#include <boost/format.hpp>
namespace UI {
@@ -103,16 +105,11 @@
}
// Print the state in percent
- char buffer[30];
-
- snprintf
- (buffer, sizeof(buffer), "%u%%", static_cast<uint32_t>(fraction * 100));
-
- UI::g_fh->draw_text
- (dst, UI::TextStyle::ui_small(),
- Point(get_w() / 2, get_h() / 2),
- buffer,
- Align_Center);
+ // TODO use UI_FNT_COLOR_BRIGHT when merged
+ uint32_t percent = static_cast<uint32_t>(fraction * 100);
+ const std::string progress_text =
+ (boost::format("<font color=%1$s>%2$i%%</font>") % "ffffff" % percent).str();
+ const Point pos(get_w() / 2, get_h() / 2);
+ dst.blit(pos, UI::g_fh1->render(as_uifont(progress_text)), CM_Normal, Align_Center);
}
-
}
=== modified file 'src/ui_basic/table.cc'
--- src/ui_basic/table.cc 2013-07-13 14:25:41 +0000
+++ src/ui_basic/table.cc 2013-07-16 17:39:34 +0000
@@ -23,11 +23,13 @@
#include "graphic/font_handler.h"
#include "graphic/graphic.h"
#include "graphic/rendertarget.h"
+#include "graphic/font_handler1.h"
#include "button.h"
#include "mouse_constants.h"
#include "scrollbar.h"
#include "wlapplication.h"
+#include "text_layout.h"
#include "container_iterate.h"
#include <boost/bind.hpp>
@@ -273,21 +275,13 @@
const std::string & entry_string = er.get_string (i);
uint32_t picw = 0;
uint32_t pich = 0;
- uint32_t stringw = 0;
- uint32_t stringh = g_fh->get_fontheight(m_fontname, m_fontsize);
+
if (entry_picture) {
picw = entry_picture->width();
pich = entry_picture->height();
}
- Point point =
- Point(curx, y)
- +
- Point
- (alignment & Align_Right ? curw - (picw + stringw) - 1 :
- alignment & Align_HCenter ? (curw - (picw + stringw)) / 2 :
- 1,
- 0);
- if (entry_picture)
+ Point point(curx, y);
+ if (entry_picture) {
dst.blit
(point +
Point
@@ -296,18 +290,13 @@
static_cast<int32_t>(pich))
/ 2),
entry_picture);
+ point.x += picw;
+ }
- UI::g_fh->draw_text
- (dst,
- TextStyle::makebold(Font::get(m_fontname, m_fontsize), er.use_clr ? er.clr : UI_FONT_CLR_FG),
- point +
- Point
- (picw,
- (static_cast<int32_t>(lineheight) -
- static_cast<int32_t>(stringh))
- / 2),
- entry_string,
- alignment);
+ const Image* entry_text_im = UI::g_fh1->render(as_uifont(entry_string, m_fontsize));
+ // Crop to column width
+ UI::correct_for_align(alignment, entry_text_im->width(), entry_text_im->height(), &point);
+ dst.blitrect(point, entry_text_im, Rect(0, 0, curw - picw, lineheight));
curx += curw;
}
=== modified file 'src/ui_fsmenu/loadgame.cc'
--- src/ui_fsmenu/loadgame.cc 2013-07-15 05:18:12 +0000
+++ src/ui_fsmenu/loadgame.cc 2013-07-16 17:39:34 +0000
@@ -29,6 +29,7 @@
#include "log.h"
#include "logic/game.h"
#include "ui_basic/messagebox.h"
+#include "timestring.h"
#include <cstdio>
@@ -203,15 +204,9 @@
m_tamapname.set_text(_(gpdp.get_mapname()));
}
- char buf[200];
+ char buf[20];
uint32_t gametime = gpdp.get_gametime();
-
- int32_t hours = gametime / 3600000;
- gametime -= hours * 3600000;
- int32_t minutes = gametime / 60000;
-
- sprintf(buf, "%02i:%02i", hours, minutes);
- m_tagametime.set_text(buf);
+ m_tagametime.set_text(gametimestring(gametime));
sprintf(buf, "%i", gpdp.get_player_nr());
m_ta_players.set_text(buf);
=== modified file 'src/ui_fsmenu/loadreplay.cc'
--- src/ui_fsmenu/loadreplay.cc 2013-07-14 16:11:41 +0000
+++ src/ui_fsmenu/loadreplay.cc 2013-07-16 17:39:34 +0000
@@ -28,6 +28,7 @@
#include "logic/game.h"
#include "logic/replay.h"
#include "ui_basic/messagebox.h"
+#include "timestring.h"
Fullscreen_Menu_LoadReplay::Fullscreen_Menu_LoadReplay() :
Fullscreen_Menu_Base("choosemapmenu.jpg"),
@@ -186,15 +187,9 @@
m_delete.set_enabled(true);
m_tamapname.set_text(gpdp.get_mapname());
- char buf[200];
+ char buf[20];
uint32_t gametime = gpdp.get_gametime();
-
- int32_t hours = gametime / 3600000;
- gametime -= hours * 3600000;
- int32_t minutes = gametime / 60000;
-
- sprintf(buf, "%02i:%02i", hours, minutes);
- m_tagametime.set_text(buf);
+ m_tagametime.set_text(gametimestring(gametime));
sprintf(buf, "%i", gpdp.get_player_nr());
m_ta_players.set_text(buf);
=== modified file 'src/ui_fsmenu/mapselect.cc'
--- src/ui_fsmenu/mapselect.cc 2013-06-15 14:35:17 +0000
+++ src/ui_fsmenu/mapselect.cc 2013-07-16 17:39:34 +0000
@@ -172,11 +172,11 @@
vbox->set_size(get_w(), 25);
vbox = new UI::Box(this, m_table.get_x(), m_table.get_y() - 60, UI::Box::Horizontal, m_table.get_w());
_add_tag_checkbox(vbox, "1v1", _("1v1"));
- _add_tag_checkbox(vbox, "2teams", _("2 Player Teams"));
- _add_tag_checkbox(vbox, "3teams", _("3 Player Teams"));
+ _add_tag_checkbox(vbox, "2teams", _("Teams of 2"));
+ _add_tag_checkbox(vbox, "3teams", _("Teams of 3"));
vbox->set_size(get_w(), 25);
vbox = new UI::Box(this, m_table.get_x(), m_table.get_y() - 30, UI::Box::Horizontal, m_table.get_w());
- _add_tag_checkbox(vbox, "4teams", _("4 Player Teams"));
+ _add_tag_checkbox(vbox, "4teams", _("Teams of 4"));
_add_tag_checkbox(vbox, "ffa", _("Free for all"));
_add_tag_checkbox(vbox, "unbalanced", _("Unbalanced"));
vbox->set_size(get_w(), 25);
=== modified file 'src/wlapplication.cc'
--- src/wlapplication.cc 2013-07-15 05:18:12 +0000
+++ src/wlapplication.cc 2013-07-16 17:39:34 +0000
@@ -2036,9 +2036,14 @@
}
} else { // normal singleplayer
uint8_t const pn = sp.settings().playernum + 1;
- boost::scoped_ptr<GameController> ctrl
- (GameController::createSinglePlayer(game, true, pn));
try {
+ // Game controller needs the ibase pointer to init
+ // the chat
+ game.set_ibase
+ (new Interactive_Player
+ (game, g_options.pull_section("global"), pn, false, false));
+ boost::scoped_ptr<GameController> ctrl
+ (GameController::createSinglePlayer(game, true, pn));
UI::ProgressWindow loaderUI;
std::vector<std::string> tipstext;
tipstext.push_back("general_game");
@@ -2052,9 +2057,6 @@
loaderUI.step(_("Preparing game"));
game.set_game_controller(ctrl.get());
- game.set_ibase
- (new Interactive_Player
- (game, g_options.pull_section("global"), pn, false, false));
game.init_newgame(&loaderUI, sp.settings());
game.run(&loaderUI, Widelands::Game::NewNonScenario);
} catch (const std::exception & e) {
=== modified file 'src/wui/building_ui.cc'
--- src/wui/building_ui.cc 2013-07-09 05:53:39 +0000
+++ src/wui/building_ui.cc 2013-07-16 17:39:34 +0000
@@ -17,6 +17,8 @@
*
*/
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
#include "buildingwindow.h"
#include "logic/building.h"
#include "ui_basic/window.h"
@@ -30,14 +32,17 @@
*/
void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick)
{
+ // Reset tooltip before opening the window
+ igbase.set_tooltip("");
if (m_optionswindow) {
if (m_optionswindow->is_minimal())
m_optionswindow->restore();
m_optionswindow->move_to_top();
} else {
create_options_window(igbase, m_optionswindow);
- if (upcast(Building_Window, bw, m_optionswindow))
+ if (upcast(Building_Window, bw, m_optionswindow)) {
bw->set_avoid_fastclick(avoid_fastclick);
+ }
// Run a first think here so that certain things like caps buttons
// get properly initialized
m_optionswindow->think();
@@ -49,6 +54,8 @@
*/
void Building::hide_options()
{
+ BOOST_FOREACH(boost::signals::connection& c, options_window_connections)
+ c.disconnect();
delete m_optionswindow;
m_optionswindow = NULL;
}
=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc 2013-07-13 15:58:52 +0000
+++ src/wui/buildingwindow.cc 2013-07-16 17:39:34 +0000
@@ -79,13 +79,6 @@
set_center_panel(vbox);
set_think(true);
- char filename[] = "pics/workarea0cumulative.png";
- compile_assert(NUMBER_OF_WORKAREA_PICS <= 9);
- for (Workarea_Info::size_type i = 0; i < NUMBER_OF_WORKAREA_PICS; ++i) {
- ++filename[13];
- workarea_cumulative_pic[i] = g_gr->images().get(filename);
- }
-
show_workarea();
set_fastclick_panel(this);
@@ -327,7 +320,7 @@
(capsbuttons, "workarea",
0, 0, 34, 34,
g_gr->images().get("pics/but4.png"),
- g_gr->images().get("pics/workarea3cumulative.png"),
+ g_gr->images().get("pics/workarea123.png"),
_("Hide workarea"));
m_toggle_workarea->sigclicked.connect
(boost::bind(&Building_Window::toggle_workarea, boost::ref(*this)));
@@ -512,41 +505,11 @@
*/
void Building_Window::show_workarea()
{
- if (m_workarea_job_id)
+ if (m_workarea_job_id) {
return; // already shown, nothing to be done
-
+ }
const Workarea_Info & workarea_info = m_building.descr().m_workarea_info;
- if (workarea_info.size() == 0)
- return; // building has no workarea
-
- Widelands::Map & map =
- ref_cast<const Interactive_GameBase, UI::Panel>(*get_parent()).egbase()
- .map();
- Overlay_Manager & overlay_manager = map.overlay_manager();
- m_workarea_job_id = overlay_manager.get_a_job_id();
-
- Widelands::HollowArea<> hollow_area
- (Widelands::Area<>(m_building.get_position(), 0), 0);
- Workarea_Info::const_iterator it = workarea_info.begin();
- for
- (Workarea_Info::size_type i =
- std::min(workarea_info.size(), NUMBER_OF_WORKAREA_PICS);
- i;
- ++it)
- {
- --i;
- hollow_area.radius = it->first;
- Widelands::MapHollowRegion<> mr(map, hollow_area);
- do
- overlay_manager.register_overlay
- (mr.location(),
- workarea_cumulative_pic[i],
- 0,
- Point::invalid(),
- m_workarea_job_id);
- while (mr.advance(map));
- hollow_area.hole_radius = hollow_area.radius;
- }
+ m_workarea_job_id = igbase().show_work_area(workarea_info, m_building.get_position());
configure_workarea_button();
}
@@ -557,11 +520,7 @@
void Building_Window::hide_workarea()
{
if (m_workarea_job_id) {
- Widelands::Map & map =
- ref_cast<const Interactive_GameBase, UI::Panel>(*get_parent()).egbase()
- .map();
- Overlay_Manager & overlay_manager = map.overlay_manager();
- overlay_manager.remove_overlay(m_workarea_job_id);
+ igbase().hide_work_area(m_workarea_job_id);
m_workarea_job_id = Overlay_Manager::Job_Id::Null();
configure_workarea_button();
=== modified file 'src/wui/buildingwindow.h'
--- src/wui/buildingwindow.h 2013-07-08 03:35:09 +0000
+++ src/wui/buildingwindow.h 2013-07-16 17:39:34 +0000
@@ -94,7 +94,6 @@
bool m_caps_setup;
Overlay_Manager::Job_Id m_workarea_job_id;
- const Image* workarea_cumulative_pic[NUMBER_OF_WORKAREA_PICS];
bool m_avoid_fastclick;
};
=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc 2013-02-09 23:36:30 +0000
+++ src/wui/fieldaction.cc 2013-07-16 17:39:34 +0000
@@ -231,7 +231,6 @@
bool m_fastclick; // if true, put the mouse over first button in first tab
uint32_t m_best_tab;
Overlay_Manager::Job_Id m_workarea_preview_job_id;
- const Image* workarea_cumulative_pic[NUMBER_OF_WORKAREA_PICS];
/// Variables to use with attack dialog.
AttackBox * m_attack_box;
@@ -297,13 +296,6 @@
set_center_panel(&m_tabpanel);
-
- char filename[] = "pics/workarea0cumulative.png";
- compile_assert(NUMBER_OF_WORKAREA_PICS <= 9);
- for (Workarea_Info::size_type i = 0; i < NUMBER_OF_WORKAREA_PICS; ++i) {
- ++filename[13];
- workarea_cumulative_pic[i] = g_gr->images().get(filename);
- }
}
@@ -856,44 +848,10 @@
(const Widelands::Building_Index::value_t idx)
{
if (ibase().m_show_workarea_preview and not m_workarea_preview_job_id) {
- m_workarea_preview_job_id = m_overlay_manager.get_a_job_id();
- Widelands::HollowArea<> hollow_area(Widelands::Area<>(m_node, 0), 0);
const Workarea_Info & workarea_info =
m_plr->tribe().get_building_descr(Widelands::Building_Index(idx))
->m_workarea_info;
- Workarea_Info::const_iterator it = workarea_info.begin();
- for
- (Workarea_Info::size_type i =
- std::min(workarea_info.size(), NUMBER_OF_WORKAREA_PICS);
- i;
- ++it)
- {
- --i;
- hollow_area.radius = it->first;
- assert(hollow_area.radius);
- assert(hollow_area.hole_radius < hollow_area.radius);
- Widelands::MapHollowRegion<> mr(*m_map, hollow_area);
- do
- m_overlay_manager.register_overlay
- (mr.location(),
- workarea_cumulative_pic[i],
- 0,
- Point::invalid(),
- m_workarea_preview_job_id);
- while (mr.advance(*m_map));
- hollow_area.hole_radius = hollow_area.radius;
- }
-
-#if 0
- // This is debug output.
- // Improvement suggestion: add to sign explanation window instead.
- container_iterate_const(Workarea_Info, workarea_info, i) {
- log("Radius: %i\n", i.current->first);
- container_iterate_const(std::set<std::string>, i.current->second, j)
- log(" %s\n", j.current->c_str());
- }
-#endif
-
+ m_workarea_preview_job_id = ibase().show_work_area(workarea_info, m_node);
}
}
=== modified file 'src/wui/game_main_menu_save_game.cc'
--- src/wui/game_main_menu_save_game.cc 2013-07-15 11:01:59 +0000
+++ src/wui/game_main_menu_save_game.cc 2013-07-16 17:39:34 +0000
@@ -28,10 +28,13 @@
#include "game_io/game_saver.h"
#include "i18n.h"
#include "interactive_gamebase.h"
+#include "gamecontroller.h"
#include "io/filesystem/filesystem.h"
#include "io/filesystem/layered_filesystem.h"
#include "logic/game.h"
#include "profile/profile.h"
+#include "interactive_player.h"
+#include "timestring.h"
using boost::format;
@@ -125,6 +128,10 @@
}
m_editbox->focus();
+ if (!parent.game().get_ipl()->is_multiplayer()) {
+ // Pause the game
+ parent.game().gameController()->setPaused(true);
+ }
}
@@ -144,20 +151,11 @@
m_button_ok->set_enabled(true);
m_name.set_text(gpdp.get_mapname());
+
+ uint32_t gametime = gpdp.get_gametime();
+ m_gametime.set_text(gametimestring(gametime));
+
char buf[200];
- uint32_t gametime = gpdp.get_gametime();
-#define SPLIT_GAMETIME(unit, factor) \
- uint32_t const unit = gametime / factor; gametime %= factor;
- SPLIT_GAMETIME(days, 86400000);
- SPLIT_GAMETIME(hours, 3600000);
- SPLIT_GAMETIME(minutes, 60000);
- SPLIT_GAMETIME(seconds, 1000);
- sprintf
- (buf,
- _("%02ud%02uh%02u'%02u\"%03u"),
- days, hours, minutes, seconds, gametime);
- m_gametime.set_text(buf);
-
sprintf
(buf, "%i %s", gpdp.get_player_nr(),
ngettext(_("player"), _("players"), gpdp.get_player_nr()));
@@ -293,6 +291,15 @@
}
}
+void Game_Main_Menu_Save_Game::die()
+{
+ UI::UniqueWindow::die();
+ if (!igbase().game().get_ipl()->is_multiplayer()) {
+ igbase().game().gameController()->setPaused(false);
+ }
+}
+
+
struct DeletionMessageBox : public UI::WLMessageBox {
DeletionMessageBox
=== modified file 'src/wui/game_main_menu_save_game.h'
--- src/wui/game_main_menu_save_game.h 2013-07-13 15:17:51 +0000
+++ src/wui/game_main_menu_save_game.h 2013-07-16 17:39:34 +0000
@@ -43,7 +43,7 @@
void select_by_name(std::string name);
private:
Interactive_GameBase & igbase();
- void die() {UI::UniqueWindow::die();}
+ void die();
void selected (uint32_t);
void double_clicked(uint32_t);
void edit_box_changed();
=== modified file 'src/wui/game_message_menu.cc'
--- src/wui/game_message_menu.cc 2013-07-12 15:11:32 +0000
+++ src/wui/game_message_menu.cc 2013-07-16 17:39:34 +0000
@@ -28,6 +28,7 @@
#include "logic/playercommand.h"
#include "container_iterate.h"
+#include "timestring.h"
using Widelands::Message;
using Widelands::Message_Id;
@@ -109,6 +110,8 @@
list->set_column_compare
(ColStatus, boost::bind(&GameMessageMenu::status_compare, this, _1, _2));
+ list->set_sort_column(ColTimeSent);
+ list->set_sort_descending(true);
set_can_focus(true);
focus();
@@ -200,19 +203,8 @@
g_gr->images().get(status_picture_filename[message.status()]));
er.set_string(ColTitle, message.title());
- uint32_t time = message.sent();
- char timestring[] = "000:00:00.000";
- timestring[12] += time % 10;
- timestring[11] += (time /= 10) % 10;
- timestring[10] += (time /= 10) % 10;
- timestring [8] += (time /= 10) % 10;
- timestring [7] += (time /= 10) % 6;
- timestring [5] += (time /= 6) % 10;
- timestring [4] += (time /= 10) % 6;
- timestring [2] += (time /= 6) % 10;
- timestring [1] += (time /= 10) % 10;
- timestring [0] += time /= 10;
- er.set_string(ColTimeSent, time < 10 ? timestring : "-------------");
+ const uint32_t time = message.sent();
+ er.set_string(ColTimeSent, gametimestring(time));
}
/*
=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc 2013-06-15 13:38:19 +0000
+++ src/wui/interactive_base.cc 2013-07-16 17:39:34 +0000
@@ -36,6 +36,7 @@
#include "logic/maptriangleregion.h"
#include "logic/player.h"
#include "logic/productionsite.h"
+#include "logic/maphollowregion.h"
#include "mapviewpixelconstants.h"
#include "mapviewpixelfunctions.h"
#include "minimap.h"
@@ -119,6 +120,15 @@
// funny results.
m_sel.pic = g_gr->images().get("pics/fsel.png");
+ // Load workarea images.
+ // Start at idx 0 for 2 enhancements, idx 3 for 1, idx 5 if none
+ workarea_pics[0] = g_gr->images().get("pics/workarea123.png");
+ workarea_pics[1] = g_gr->images().get("pics/workarea23.png");
+ workarea_pics[2] = g_gr->images().get("pics/workarea3.png");
+ workarea_pics[3] = g_gr->images().get("pics/workarea12.png");
+ workarea_pics[4] = g_gr->images().get("pics/workarea2.png");
+ workarea_pics[5] = g_gr->images().get("pics/workarea1.png");
+
m_label_speed.set_visible(false);
m_label_speed_shadow.set_visible(false);
@@ -229,6 +239,60 @@
egbase().map().overlay_manager().show_buildhelp(t);
}
+// Show the given workareas at the given coords and returns the overlay job id associated
+Overlay_Manager::Job_Id Interactive_Base::show_work_area
+ (const Workarea_Info & workarea_info, Widelands::Coords coords)
+{
+ uint8_t workareas_nrs = workarea_info.size();
+ Workarea_Info::size_type wa_index;
+ switch (workareas_nrs) {
+ case 0: return Overlay_Manager::Job_Id::Null(); break; // no workarea
+ case 1: wa_index = 5; break;
+ case 2: wa_index = 3; break;
+ case 3: wa_index = 0; break;
+ default: assert(false); break;
+ }
+ Widelands::Map & map = m_egbase.map();
+ Overlay_Manager & overlay_manager = map.overlay_manager();
+ Overlay_Manager::Job_Id job_id = overlay_manager.get_a_job_id();
+
+ Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
+
+ // Iterate through the work areas, from building to its enhancement
+ Workarea_Info::const_iterator it = workarea_info.begin();
+ for (; it != workarea_info.end(); ++it) {
+ assert(wa_index < NUMBER_OF_WORKAREA_PICS);
+ hollow_area.radius = it->first;
+ Widelands::MapHollowRegion<> mr(map, hollow_area);
+ do
+ overlay_manager.register_overlay
+ (mr.location(),
+ workarea_pics[wa_index],
+ 0,
+ Point::invalid(),
+ job_id);
+ while (mr.advance(map));
+ wa_index++;
+ hollow_area.hole_radius = hollow_area.radius;
+ }
+ return job_id;
+#if 0
+ // This is debug output.
+ // Improvement suggestion: add to sign explanation window instead.
+ container_iterate_const(Workarea_Info, workarea_info, i) {
+ log("Radius: %i\n", i.current->first);
+ container_iterate_const(std::set<std::string>, i.current->second, j)
+ log(" %s\n", j.current->c_str());
+ }
+#endif
+}
+
+void Interactive_Base::hide_work_area(Overlay_Manager::Job_Id job_id) {
+ Widelands::Map & map = m_egbase.map();
+ Overlay_Manager & overlay_manager = map.overlay_manager();
+ overlay_manager.remove_overlay(job_id);
+}
+
/**
* Called by \ref Game::postload at the end of the game loading
=== modified file 'src/wui/interactive_base.h'
--- src/wui/interactive_base.h 2013-02-10 19:36:24 +0000
+++ src/wui/interactive_base.h 2013-07-16 17:39:34 +0000
@@ -60,6 +60,8 @@
virtual void reference_player_tribe(Widelands::Player_Number, const void * const) {}
bool m_show_workarea_preview;
+ Overlay_Manager::Job_Id show_work_area(const Workarea_Info & workarea_info, Widelands::Coords coords);
+ void hide_work_area(Overlay_Manager::Job_Id job_id);
// point of view for drawing
virtual Widelands::Player * get_player() const throw () = 0;
@@ -151,6 +153,7 @@
Overlay_Manager::Job_Id m_road_buildhelp_overlay_jobid;
Widelands::CoordPath * m_buildroad; // path for the new road
Widelands::Player_Number m_road_build_player;
+ const Image* workarea_pics[NUMBER_OF_WORKAREA_PICS];
protected:
void toggle_minimap();
=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc 2013-02-21 19:02:21 +0000
+++ src/wui/interactive_player.cc 2013-07-16 17:39:34 +0000
@@ -85,7 +85,8 @@
:
Interactive_GameBase (_game, global_s),
m_auto_roadbuild_mode(global_s.get_bool("auto_roadbuild_mode", true)),
-m_flag_to_connect(Widelands::Coords::Null()),
+ m_flag_to_connect(Widelands::Coords::Null()),
+ m_multiplayer(multiplayer),
// Chat is different, as m_chatProvider needs to be checked when toggling
// Buildhelp is different as it does not toggle a UniqueWindow
@@ -152,16 +153,16 @@
m_toolbar.add(&m_toggle_statistics_menu, UI::Box::AlignLeft);
m_toolbar.add(&m_toggle_minimap, UI::Box::AlignLeft);
m_toolbar.add(&m_toggle_buildhelp, UI::Box::AlignLeft);
+ // Limit chat width to half the screen, to limit the damage lamers can do
+ // by flooding chat messages
+ m_chatOverlay =
+ new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25);
if (multiplayer) {
m_toolbar.add(&m_toggle_chat, UI::Box::AlignLeft);
- // Limit chat width to half the screen, to limit the damage lamers can do
- // by flooding chat messages
- m_chatOverlay =
- new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25);
m_toggle_chat.set_visible(false);
m_toggle_chat.set_enabled(false);
- } else
- m_toggle_chat.set_visible(false);
+ }
+
m_toolbar.add(&m_toggle_help, UI::Box::AlignLeft);
if (not scenario)
m_toggle_objectives.set_visible(false);
@@ -283,8 +284,10 @@
m_flag_to_connect = Widelands::Coords::Null();
}
}
- m_toggle_chat.set_visible(m_chatenabled);
- m_toggle_chat.set_enabled(m_chatenabled);
+ if (m_multiplayer) {
+ m_toggle_chat.set_visible(m_chatenabled);
+ m_toggle_chat.set_enabled(m_chatenabled);
+ }
{
char buffer[128];
char const * msg_icon = "pics/menu_toggle_oldmessage_menu.png";
@@ -452,7 +455,7 @@
case SDLK_KP_ENTER:
case SDLK_RETURN:
- if (!m_chatProvider | !m_chatenabled)
+ if (!m_chatProvider | !m_chatenabled || !m_multiplayer)
break;
if (!m_chat.window)
=== modified file 'src/wui/interactive_player.h'
--- src/wui/interactive_player.h 2013-02-10 19:36:24 +0000
+++ src/wui/interactive_player.h 2013-07-16 17:39:34 +0000
@@ -88,12 +88,15 @@
void popup_message(Widelands::Message_Id, const Widelands::Message &);
+ bool is_multiplayer() {return m_multiplayer;}
+
private:
void cmdSwitchPlayer(const std::vector<std::string> & args);
Widelands::Player_Number m_player_number;
bool m_auto_roadbuild_mode;
Widelands::Coords m_flag_to_connect;
+ bool m_multiplayer;
UI::Button m_toggle_chat;
UI::Button m_toggle_options_menu;
=== modified file 'src/wui/productionsitewindow.cc'
--- src/wui/productionsitewindow.cc 2013-02-10 19:36:24 +0000
+++ src/wui/productionsitewindow.cc 2013-07-16 17:39:34 +0000
@@ -105,13 +105,41 @@
worker_box,
productionsite().descr().nr_working_positions() > 1 ?
_("Workers") : _("Worker"));
+ update_worker_table();
}
}
void ProductionSite_Window::think()
{
Building_Window::think();
-
+ // If we have pending requests, update table as the worker might be coming
+ for
+ (unsigned int i = 0;
+ i < productionsite().descr().nr_working_positions(); ++i)
+ {
+ if (productionsite().working_positions()[i].worker_request) {
+ update_worker_table();
+ break;
+ }
+ }
+}
+
+/*
+===============
+Create the production site information window.
+===============
+*/
+void ProductionSite::create_options_window
+ (Interactive_GameBase & parent, UI::Window * & registry)
+{
+ ProductionSite_Window* win = new ProductionSite_Window(parent, *this, registry);
+ options_window_connections.push_back
+ (workers_changed.connect(boost::bind
+ (&ProductionSite_Window::update_worker_table, boost::ref(*win))));
+}
+
+void ProductionSite_Window::update_worker_table()
+{
if (m_worker_table) {
assert
(productionsite().descr().nr_working_positions() ==
@@ -155,7 +183,7 @@
er.set_string(1, "---");
er.set_string(2, "---");
}
- } else {
+ } else if (request) {
const Widelands::Worker_Descr * desc =
productionsite().tribe().get_worker_descr(request->get_index());
er.set_picture
@@ -164,20 +192,13 @@
er.set_string(1, "");
er.set_string(2, "");
+ } else {
+ // Occurs during cleanup
+ return;
}
}
}
-}
-
-/*
-===============
-Create the production site information window.
-===============
-*/
-void ProductionSite::create_options_window
- (Interactive_GameBase & parent, UI::Window * & registry)
-{
- new ProductionSite_Window(parent, *this, registry);
+ m_worker_table->update();
}
void ProductionSite_Window::evict_worker() {
=== modified file 'src/wui/productionsitewindow.h'
--- src/wui/productionsitewindow.h 2013-02-02 14:42:48 +0000
+++ src/wui/productionsitewindow.h 2013-07-16 17:39:34 +0000
@@ -33,7 +33,7 @@
Widelands::ProductionSite & productionsite() {
return ref_cast<Widelands::ProductionSite, Widelands::Building>(building());
}
-
+ void update_worker_table();
protected:
virtual void think();
void evict_worker();
Follow ups