widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #01208
[Merge] lp:~widelands-dev/widelands/csite_improvement into lp:widelands
cghislai has proposed merging lp:~widelands-dev/widelands/csite_improvement into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #580905 in widelands: "write building status in a different font color for construction sites"
https://bugs.launchpad.net/widelands/+bug/580905
Bug #722087 in widelands: "hard to empty warehouse"
https://bugs.launchpad.net/widelands/+bug/722087
Bug #803284 in widelands: "While building, show range of the building on construction site"
https://bugs.launchpad.net/widelands/+bug/803284
Bug #1108083 in widelands: "Construction site window does not display specific building name"
https://bugs.launchpad.net/widelands/+bug/1108083
Bug #1132238 in widelands: "Open buildingwindow after closing of constructionsitewindow when construction has finished"
https://bugs.launchpad.net/widelands/+bug/1132238
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/csite_improvement/+merge/174623
This contains a bunch of improvements not all related to construction sites
- Colored string for production efficiency and trends
- Anchored selection for ware selection in warehouses/economy settings
- Range of building shown for construction sites
- Building name shown in construction site windows
- Building window opened when construction site window was open and construction ended
--
https://code.launchpad.net/~widelands-dev/widelands/csite_improvement/+merge/174623
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/csite_improvement into lp:widelands.
=== modified file 'src/constants.h'
--- src/constants.h 2013-07-13 14:32:49 +0000
+++ src/constants.h 2013-07-14 21:52:24 +0000
@@ -80,9 +80,11 @@
#define PROSA_FONT_CLR_FG RGBColor(255, 255, 0)
/// Colors for good/ok/bad
-#define UI_FONT_CLR_BAD_HEX "ff0000"
-#define UI_FONT_CLR_OK_HEX "ffff00"
-#define UI_FONT_CLR_GOOD_HEX "325b1f"
+#define UI_FONT_CLR_BRIGHT_HEX "fffaaa"
+#define UI_FONT_CLR_DARK_HEX "a39013"
+#define UI_FONT_CLR_BAD_HEX "bb0000"
+#define UI_FONT_CLR_OK_HEX "ffe11e"
+#define UI_FONT_CLR_GOOD_HEX "00bb00"
//@}
/** \name Text colors
=== modified file 'src/logic/building.h'
--- src/logic/building.h 2013-07-14 10:38:26 +0000
+++ src/logic/building.h 2013-07-14 21:52:24 +0000
@@ -183,7 +183,7 @@
virtual bool burn_on_destroy();
virtual void destroy(Editor_Game_Base &);
- void show_options(Interactive_GameBase &, bool avoid_fastclick = false);
+ void show_options(Interactive_GameBase &, bool avoid_fastclick = false, Point pos = Point(- 1, - 1));
void hide_options();
void refresh_options(Interactive_GameBase &);
=== modified file 'src/logic/constructionsite.cc'
--- src/logic/constructionsite.cc 2013-07-14 10:38:26 +0000
+++ src/logic/constructionsite.cc 2013-07-14 21:52:24 +0000
@@ -25,17 +25,20 @@
#include "upcast.h"
#include "wexception.h"
-#include "graphic/animation.h"
#include "economy/wares_queue.h"
#include "game.h"
+#include "graphic/animation.h"
#include "graphic/graphic.h"
#include "graphic/rendertarget.h"
#include "sound/sound_handler.h"
+#include "ui_basic/window.h"
+#include "wui/interactive_gamebase.h"
#include "tribe.h"
#include "worker.h"
#include "constructionsite.h"
+
namespace Widelands {
ConstructionSite_Descr::ConstructionSite_Descr
@@ -86,14 +89,9 @@
std::string ConstructionSite::get_statistics_string()
{
unsigned int percent = (get_built_per64k() * 100) >> 16;
-
- std::string clr = UI_FONT_CLR_OK_HEX;
- if (percent <= 25) clr = UI_FONT_CLR_BAD_HEX;
- else if (percent >= 75) clr = UI_FONT_CLR_GOOD_HEX;
-
- std::string perc_s = (boost::format("<font color=%s>%i</font>") % clr % percent).str();
-
- return (boost::format(_("%s%% built")) % perc_s.c_str()).str();
+ std::string perc_s =
+ (boost::format("<font color=%1$s>%2$i%% built</font>") % UI_FONT_CLR_DARK_HEX % percent).str();
+ return perc_s;
}
/*
@@ -102,9 +100,11 @@
=======
*/
WaresQueue & ConstructionSite::waresqueue(Ware_Index const wi) {
- container_iterate_const(Wares, m_wares, i)
- if ((*i.current)->get_ware() == wi)
+ container_iterate_const(Wares, m_wares, i) {
+ if ((*i.current)->get_ware() == wi) {
return **i.current;
+ }
+ }
throw wexception
("%s (%u) (building %s) has no WaresQueue for %u",
name().c_str(), serial(), m_building->name().c_str(), wi.value());
@@ -183,6 +183,14 @@
builder->reset_tasks(ref_cast<Game, Editor_Game_Base>(egbase));
builder->set_location(&b);
}
+ // Open the new building window if needed
+ if (m_optionswindow) {
+ Point window_position = m_optionswindow->get_pos();
+ hide_options();
+ Interactive_GameBase & igbase =
+ ref_cast<Interactive_GameBase, Interactive_Base>(*egbase.get_ibase());
+ b.show_options(igbase, false, window_position);
+ }
}
}
=== modified file 'src/logic/productionsite.cc'
--- src/logic/productionsite.cc 2013-05-25 09:30:35 +0000
+++ src/logic/productionsite.cc 2013-07-14 21:52:24 +0000
@@ -18,6 +18,7 @@
*/
#include <libintl.h>
+#include <boost/format.hpp>
#include "helper.h"
#include "i18n.h"
@@ -242,21 +243,21 @@
uint32_t nr_workers = 0;
for (uint32_t i = nr_working_positions; i;)
nr_workers += m_working_positions[--i].worker ? 1 : 0;
- if (!nr_workers)
- return _("(not occupied)");
- else if (uint32_t const nr_requests = nr_working_positions - nr_workers) {
- char buffer[1000];
- snprintf
- (buffer, sizeof(buffer), "%s",
- ngettext("Worker missing", "Workers missing", nr_requests));
- return buffer;
+ if (!nr_workers) {
+ return
+ (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX % _("(not occupied)")).str();
+ } else if (uint32_t const nr_requests = nr_working_positions - nr_workers) {
+ return (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX
+ % ngettext(_("Worker missing"), _("Workers missing"), nr_requests)).str();
}
- if (m_statistics_changed)
+ if (m_statistics_changed) {
calc_statistics();
+ }
- if (m_is_stopped)
- return _("(stopped)");
+ if (m_is_stopped) {
+ return (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BRIGHT_HEX % _("(stopped)")).str();
+ }
return m_statistics_buffer;
}
@@ -315,21 +316,43 @@
++lastOk;
}
}
- uint8_t const percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH;
- uint8_t const lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2);
-
- const std::string trend =
- lastPercOk > percOk ? "+" : lastPercOk < percOk ? "-" : "=";
-
- if (0 < percOk and percOk < 100)
- snprintf
- (m_statistics_buffer, sizeof(m_statistics_buffer),
- "%d%% %s", percOk, trend.c_str());
+ // Somehow boost::format doesn't handle correctly uint8_t in this case
+ unsigned int percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH;
+ unsigned int lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2);
+
+ std::string color;
+ if (percOk < 33)
+ color = UI_FONT_CLR_BAD_HEX;
+ else if (percOk < 66)
+ color = UI_FONT_CLR_OK_HEX;
else
- snprintf
- (m_statistics_buffer, sizeof(m_statistics_buffer),
- "%d%%", percOk);
-
+ color = UI_FONT_CLR_GOOD_HEX;
+ const std::string perc_str =
+ (boost::format("<font color=%1$s>%2$i%%</font>") % color % percOk).str();
+
+ std::string trend;
+ if (lastPercOk > percOk) {
+ color = UI_FONT_CLR_GOOD_HEX;
+ trend = "+";
+ } else if (lastPercOk < percOk) {
+ color = UI_FONT_CLR_BAD_HEX;
+ trend = "-";
+ } else {
+ color = UI_FONT_CLR_BRIGHT_HEX;
+ trend = "=";
+ }
+ const std::string trend_str =
+ (boost::format("<font color=%s>%s</font>") % color % trend).str();
+
+ if (0 < percOk and percOk < 100) {
+ snprintf
+ (m_statistics_buffer, sizeof(m_statistics_buffer),
+ "%s %s", perc_str.c_str(), trend_str.c_str());
+ } else {
+ snprintf
+ (m_statistics_buffer, sizeof(m_statistics_buffer),
+ "%s", perc_str.c_str());
+ }
m_last_stat_percent = percOk;
m_statistics_changed = false;
=== modified file 'src/logic/productionsite.h'
--- src/logic/productionsite.h 2013-04-22 20:15:00 +0000
+++ src/logic/productionsite.h 2013-07-14 21:52:24 +0000
@@ -256,7 +256,7 @@
Input_Queues m_input_queues; ///< input queues for all inputs
std::vector<bool> m_statistics;
bool m_statistics_changed;
- char m_statistics_buffer[40];
+ char m_statistics_buffer[128];
char m_result_buffer [213];
uint8_t m_last_stat_percent;
bool m_is_stopped;
=== 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-14 21:52:24 +0000
@@ -28,7 +28,7 @@
* Create the building's options window if necessary and bring it to
* the top to be seen by the player.
*/
-void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick)
+void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick, Point pos)
{
if (m_optionswindow) {
if (m_optionswindow->is_minimal())
@@ -42,6 +42,9 @@
// get properly initialized
m_optionswindow->think();
}
+ if (pos.x >= 0 && pos.y >= 0) {
+ m_optionswindow->set_pos(pos);
+ }
}
/**
=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc 2013-07-13 15:58:52 +0000
+++ src/wui/buildingwindow.cc 2013-07-14 21:52:24 +0000
@@ -23,6 +23,7 @@
#include "graphic/image.h"
#include "graphic/rendertarget.h"
#include "interactive_player.h"
+#include "logic/constructionsite.h"
#include "logic/dismantlesite.h"
#include "logic/maphollowregion.h"
#include "logic/militarysite.h"
@@ -36,7 +37,6 @@
#include "waresqueuedisplay.h"
#include "buildingwindow.h"
-#include "logic/militarysite.h"
static const char * pic_bulldoze = "pics/menu_bld_bulldoze.png";
static const char * pic_dismantle = "pics/menu_bld_dismantle.png";
@@ -78,17 +78,25 @@
set_center_panel(vbox);
set_think(true);
+ set_fastclick_panel(this);
+ // Work area
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);
+ // Title for construction site
+ upcast(Widelands::ConstructionSite, csite, &m_building);
+ if (csite != NULL) {
+ char cs_title[256];
+ // Show name in parenthesis as it may take all width already
+ sprintf(cs_title, _("(%s)"), csite->building().descname().c_str());
+ set_title(cs_title);
+ }
}
@@ -512,12 +520,20 @@
*/
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)
+ Workarea_Info workarea_info;
+ upcast(Widelands::ConstructionSite, csite, &m_building);
+ if (csite != NULL) {
+ workarea_info = csite->building().m_workarea_info;
+ } else {
+ 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()
=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc 2013-03-01 23:12:08 +0000
+++ src/wui/waresdisplay.cc 2013-07-14 21:52:24 +0000
@@ -63,8 +63,12 @@
m_hidden
(m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers()
: m_tribe.get_nrwares(), false),
+ m_in_selection
+ (m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers()
+ : m_tribe.get_nrwares(), false),
m_selectable(selectable),
m_horizontal(horizontal),
+ m_selection_anchor(Widelands::Ware_Index::Null()),
m_callback_function(callback_function)
{
//resize the configuration of our wares if they won't fit in the current window
@@ -104,6 +108,9 @@
.c_str()
:
"");
+ if (m_selection_anchor) {
+ update_anchor_selection(x, y);
+ }
return true;
}
@@ -117,6 +124,12 @@
if (m_selectable) {
toggle_ware(ware);
+ // Mouserelase may be skipped sometimes here, so
+ // only anchor if needed.
+ if (!m_selection_anchor) {
+ // Anchor needs to be toggled for code consistency
+ m_selection_anchor = ware;
+ }
}
return true;
}
@@ -124,6 +137,32 @@
return UI::Panel::handle_mousepress(btn, x, y);
}
+bool AbstractWaresDisplay::handle_mouserelease(Uint8 btn, int32_t x, int32_t y)
+{
+ if (btn != SDL_BUTTON_LEFT || !m_selection_anchor) {
+ return UI::Panel::handle_mouserelease(btn, x, y);
+ }
+ Widelands::Ware_Index const number =
+ m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers() : m_tribe.get_nrwares();
+
+ for (Widelands::Ware_Index i = Widelands::Ware_Index::First();
+ i < number; ++i) {
+ if (!m_in_selection[i]) {
+ continue;
+ }
+ if (ware_selected(m_selection_anchor)) {
+ select_ware(i);
+ } else {
+ unselect_ware(i);
+ }
+ }
+ // Release anchor, empty selection
+ m_selection_anchor = Widelands::Ware_Index::Null();
+ std::fill(m_in_selection.begin(), m_in_selection.end(), false);
+ return true;
+}
+
+
/**
* Returns the index of the ware under the given coordinates, or
* WareIndex::Null() if the given point is outside the range.
@@ -151,6 +190,63 @@
return Widelands::Ware_Index::Null();
}
+void AbstractWaresDisplay::update_anchor_selection(int32_t x, int32_t y)
+{
+ if (!m_selection_anchor || x < 0 || y < 0) {
+ return;
+ }
+
+ std::fill(m_in_selection.begin(), m_in_selection.end(), false);
+ Point pos0 = ware_position(m_selection_anchor);
+ // Add an offset to make sure the anchor line and column will be
+ // selected when selecting in topleft direction
+ int32_t x0 = pos0.x + 3;
+ int32_t y0 = pos0.y + 3;
+
+ unsigned int i0 = x0 / (WARE_MENU_PIC_WIDTH + 4);
+ unsigned int j0 = y0 / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3);
+ unsigned int i = x / (WARE_MENU_PIC_WIDTH + 4);
+ unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3);
+ unsigned int s;
+ // Reverse col/row and anchor/endpoint if needed
+ if (m_horizontal) {
+ s = i0;
+ i0 = j0;
+ j0 = s;
+ s = i;
+ i = j;
+ j = s;
+ }
+ if (i0 > i) {
+ s = i0;
+ i0 = i;
+ i = s;
+ }
+ if (j0 > j) {
+ s = j0;
+ j0 = j;
+ j = s;
+ }
+
+ for (unsigned int cur_i = i0; cur_i <= i; cur_i++) {
+ if (cur_i >= icons_order().size()) {
+ continue;
+ }
+ for (unsigned cur_j = j0; cur_j <= j; cur_j++) {
+ if (cur_j >= icons_order()[cur_i].size()) {
+ continue;
+ }
+ Widelands::Ware_Index ware = icons_order()[cur_i][cur_j];
+ if (m_hidden[ware]) {
+ continue;
+ }
+ m_in_selection[ware] = true;
+ }
+ }
+ update();
+}
+
+
void AbstractWaresDisplay::layout()
{
@@ -241,9 +337,18 @@
{
Point p = ware_position(id);
+ bool draw_selected = m_selected[id];
+ if (m_selection_anchor) {
+ if (ware_selected(m_selection_anchor)) {
+ draw_selected |= m_in_selection[id];
+ } else {
+ draw_selected &= !m_in_selection[id];
+ }
+ }
+
// draw a background
const Image* bgpic =
- g_gr->images().get(ware_selected(id) ? "pics/ware_list_bg_selected.png" : "pics/ware_list_bg.png");
+ g_gr->images().get(draw_selected ? "pics/ware_list_bg_selected.png" : "pics/ware_list_bg.png");
uint16_t w = bgpic->width();
dst.blit(p, bgpic);
=== modified file 'src/wui/waresdisplay.h'
--- src/wui/waresdisplay.h 2013-02-09 22:51:15 +0000
+++ src/wui/waresdisplay.h 2013-07-14 21:52:24 +0000
@@ -56,9 +56,8 @@
bool handle_mousemove
(uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff);
-
bool handle_mousepress(uint8_t btn, int32_t x, int32_t y);
-
+ bool handle_mouserelease(Uint8 btn, int32_t x, int32_t y);
// Wares may be selected (highlighted)
void select_ware(Widelands::Ware_Index);
@@ -100,13 +99,18 @@
typedef std::vector<const Widelands::WareList *> vector_type;
typedef std::vector<bool> selection_type;
+ // Temporary achored selection
+ void update_anchor_selection(int32_t x, int32_t y);
+
const Widelands::Tribe_Descr & m_tribe;
Widelands::WareWorker m_type;
UI::Textarea m_curware;
selection_type m_selected;
selection_type m_hidden;
+ selection_type m_in_selection; //Wares in temporary achored selection
bool m_selectable;
bool m_horizontal;
+ Widelands::Ware_Index m_selection_anchor;
boost::function<void(Widelands::Ware_Index, bool)> m_callback_function;
};
Follow ups