← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~gamag/widelands/building_costs_preview into lp:widelands

 

Gabriel Margiani has proposed merging lp:~gamag/widelands/building_costs_preview into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #740401 in widelands: "Preview required building costs before building or upgrading"
  https://bugs.launchpad.net/widelands/+bug/740401

For more details, see:
https://code.launchpad.net/~gamag/widelands/building_costs_preview/+merge/111946

Adds the building costs preview as discussed in http://wl.widelands.org/forum/topic/601/
(it resizes the window always)
in the same way a preview of the enhance costs and the the wares you get back by dismantling
the building is added to the building window. 
(this wasn't discussed, so lets do it now)

-- 
https://code.launchpad.net/~gamag/widelands/building_costs_preview/+merge/111946
Your team Widelands Developers is requested to review the proposed merge of lp:~gamag/widelands/building_costs_preview into lp:widelands.
=== modified file 'src/logic/dismantlesite.cc'
--- src/logic/dismantlesite.cc	2011-11-30 21:38:37 +0000
+++ src/logic/dismantlesite.cc	2012-06-25 21:55:27 +0000
@@ -104,16 +104,39 @@
 {
 	Partially_Finished_Building::init(egbase);
 
-	Tribe_Descr const & t = tribe();
-	Building_Descr const * bd = m_building;
+	std::map<Ware_Index, uint8_t> wares;
+	count_returned_wares(*m_building, wares);
+
+	std::map<Ware_Index, uint8_t>::const_iterator it = wares.begin();
+	m_wares.resize(wares.size());
+
+	for (size_t i = 0; i < wares.size(); ++i, ++it) {
+		WaresQueue & wq =
+			*(m_wares[i] = new WaresQueue(*this, it->first, it->second));
+
+		wq.set_filled(it->second);
+		m_work_steps += it->second;
+	}
+}
+
+/*
+===============
+Count wich wares you get back if you dismantle the given building
+===============
+*/
+void DismantleSite::count_returned_wares
+	(const Widelands::Building_Descr & building,
+	 std::map<Ware_Index, uint8_t>   & res)
+{
+	Tribe_Descr const & t = building.tribe();
+	Building_Descr const * bd = &building;
 	Building_Index bd_idx = t.building_index(bd->name());
 
-	std::map<Ware_Index, uint8_t> all_costs;
 	bool done = false;
 	while (not done) {
 		std::map<Ware_Index, uint8_t> const & buildcost = bd->buildcost();
 		for (std::map<Ware_Index, uint8_t>::const_iterator i = buildcost.begin(); i != buildcost.end(); ++i)
-			all_costs[i->first] += i->second;
+			res[i->first] += i->second;
 
 		// Find the (first) predecessor of this building
 		for (Building_Index i = Building_Index::First(); i < t.get_nrbuildings(); ++i) {
@@ -128,17 +151,8 @@
 		}
 	}
 
-	std::map<Ware_Index, uint8_t>::const_iterator it = all_costs.begin();
-
-	m_wares.resize(all_costs.size());
-
-	for (size_t i = 0; i < all_costs.size(); ++i, ++it) {
-		uint8_t nwares = (it->second + RATIO_RETURNED_WARES - 1) / RATIO_RETURNED_WARES;
-		WaresQueue & wq =
-			*(m_wares[i] = new WaresQueue(*this, it->first, nwares));
-
-		wq.set_filled(nwares);
-		m_work_steps += nwares;
+	for (std::map<Ware_Index, uint8_t>::iterator it = res.begin(); it != res.end(); ++it) {
+		it->second = (it->second + RATIO_RETURNED_WARES - 1) / RATIO_RETURNED_WARES;
 	}
 }
 

=== modified file 'src/logic/dismantlesite.h'
--- src/logic/dismantlesite.h	2011-11-30 21:38:37 +0000
+++ src/logic/dismantlesite.h	2012-06-25 21:55:27 +0000
@@ -73,6 +73,8 @@
 
 	virtual bool get_building_work(Game &, Worker &, bool success);
 
+	static void count_returned_wares(const Building_Descr & building, std::map<Ware_Index, uint8_t> & res);
+
 protected:
 	virtual uint32_t build_step_time() const {return DISMANTLESITE_STEP_TIME;}
 

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2012-02-15 21:25:34 +0000
+++ src/ui_basic/button.cc	2012-06-25 21:55:27 +0000
@@ -288,6 +288,11 @@
 	if (oldhl == m_highlighted)
 		return;
 
+	if (m_highlighted)
+		sigmousein();
+	else
+		sigmouseout();
+
 	update();
 }
 

=== modified file 'src/ui_basic/button.h'
--- src/ui_basic/button.h	2012-02-15 21:25:34 +0000
+++ src/ui_basic/button.h	2012-06-25 21:55:27 +0000
@@ -87,6 +87,8 @@
 	void set_draw_flat_background(bool set);
 
 	boost::signal<void ()> sigclicked;
+	boost::signal<void ()> sigmousein;
+	boost::signal<void ()> sigmouseout;
 
 protected:
 	virtual void clicked() {} /// Override this to react on the click.

=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc	2012-02-20 15:54:26 +0000
+++ src/wui/buildingwindow.cc	2012-06-25 21:55:27 +0000
@@ -27,6 +27,7 @@
 #include "logic/player.h"
 #include "logic/productionsite.h"
 #include "logic/tribe.h"
+#include "logic/dismantlesite.h"
 #include "ui_basic/tabpanel.h"
 #include "upcast.h"
 #include "waresqueuedisplay.h"
@@ -71,6 +72,17 @@
 	// actually create buttons on the first call to think(),
 	// so that overriding create_capsbuttons() works
 
+	UI::Box * prevbox = new UI::Box(vbox, 0, 0, UI::Box::Vertical);
+
+	m_prevtext = new UI::Textarea(prevbox);
+	m_prevtext->set_desired_size(0, 0);
+	prevbox->add(m_prevtext, UI::Box::AlignLeft);
+
+	m_enhancecostPrev = new WaresMapDisplay(prevbox, 0, 0, 10, m_building.tribe(), NULL);
+	prevbox->add(m_enhancecostPrev, UI::Box::AlignLeft);
+
+	vbox->add(prevbox, UI::Box::AlignLeft);
+
 	set_center_panel(vbox);
 	set_think(true);
 
@@ -194,13 +206,22 @@
 						new UI::Button
 							(capsbuttons, "enhance", 0, 0, 34, 34,
 							 g_gr->get_picture(PicMod_UI, "pics/but4.png"),
-							 building_descr.get_buildicon(), //  button id = building id)
-							 buffer);
+							 building_descr.get_buildicon()); //  button id = building id)
 					enhancebtn->sigclicked.connect
 						(boost::bind
 							(&Building_Window::act_enhance,
 							 boost::ref(*this),
 							 boost::ref(*i.current)));
+					enhancebtn->sigmousein.connect
+						(boost::bind
+							(&Building_Window::show_costPrev,
+							 boost::ref(*this),
+							 boost::ref
+								(*reinterpret_cast<WaresMapDisplay::maptype const *>
+									(&building_descr.buildcost())),
+							 std::string(buffer)));
+					enhancebtn->sigmouseout.connect
+						(boost::bind(&Building_Window::hide_costPrev, boost::ref(*this)));
 					capsbuttons->add
 						(enhancebtn,
 						 UI::Box::AlignCenter);
@@ -222,13 +243,22 @@
 		}
 
 		if (m_capscache & Widelands::Building::PCap_Dismantle) {
+			WaresMapDisplay::maptype wares;
+			Widelands::DismantleSite::count_returned_wares(m_building.descr(), wares);
 			UI::Button * dismantlebtn =
 				new UI::Button
 					(capsbuttons, "dismantle", 0, 0, 34, 34,
 					 g_gr->get_picture(PicMod_UI, "pics/but4.png"),
-					 g_gr->get_picture(PicMod_Game, pic_dismantle),
-					 _("Dismantle"));
+					 g_gr->get_picture(PicMod_Game, pic_dismantle));
 			dismantlebtn->sigclicked.connect(boost::bind(&Building_Window::act_dismantle, boost::ref(*this)));
+			dismantlebtn->sigmousein.connect
+				(boost::bind
+					(&Building_Window::show_costPrev,
+					 boost::ref(*this),
+					 wares,
+					 _("Dismantle")));
+			dismantlebtn->sigmouseout.connect
+				(boost::bind(&Building_Window::hide_costPrev, boost::ref(*this)));
 			capsbuttons->add
 				(dismantlebtn,
 				 UI::Box::AlignCenter);
@@ -361,6 +391,29 @@
 		 igbase().game().map().get_fcoords(m_building.get_position()));
 }
 
+/*
+===============
+Show the enhancecosts / dismanteleresults preview
+===============
+*/
+void Building_Window::show_costPrev(WaresMapDisplay::maptype const & cost, std::string text)
+{
+	m_enhancecostPrev->set_map(&cost);
+	m_prevtext->set_text(text);
+}
+
+/*
+===============
+Hide the Preview
+===============
+*/
+void Building_Window::hide_costPrev()
+{
+	m_enhancecostPrev->set_map(NULL);
+	m_prevtext->set_text("");
+	m_prevtext->set_desired_size(0, 0);
+}
+
 /**
  * Show the building's workarea (if it has one).
  */

=== modified file 'src/wui/buildingwindow.h'
--- src/wui/buildingwindow.h	2012-02-15 21:25:34 +0000
+++ src/wui/buildingwindow.h	2012-06-25 21:55:27 +0000
@@ -25,6 +25,7 @@
 #include "interactive_gamebase.h"
 #include "ui_basic/button.h"
 #include "ui_basic/window.h"
+#include "waresdisplay.h"
 
 /**
  * Base class for all building windows.
@@ -66,6 +67,8 @@
 	void act_start_stop();
 	void act_enhance(Widelands::Building_Index);
 	void clicked_goto();
+	void show_costPrev(WaresMapDisplay::maptype const & cost, std::string text);
+	void hide_costPrev();
 
 	void create_ware_queue_panel
 		(UI::Box *, Widelands::Building &, Widelands::WaresQueue *, bool = false);
@@ -80,6 +83,9 @@
 
 	UI::Tab_Panel * m_tabs;
 
+	UI::Textarea * m_prevtext;
+	WaresMapDisplay * m_enhancecostPrev;
+
 	UI::Box * m_capsbuttons; ///< \ref UI::Box that contains capabilities buttons
 	UI::Button * m_toggle_workarea;
 

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2012-02-20 15:54:26 +0000
+++ src/wui/fieldaction.cc	2012-06-25 21:55:27 +0000
@@ -37,6 +37,7 @@
 #include "logic/tribe.h"
 #include "logic/warehouse.h"
 #include "military_box.h"
+#include "waresdisplay.h"
 #include "watchwindow.h"
 
 #include "ui_basic/box.h"
@@ -221,6 +222,8 @@
 
 	Widelands::FCoords  m_node;
 
+	UI::Box m_box;
+	WaresMapDisplay m_buildcostPrev;
 	UI::Tab_Panel      m_tabpanel;
 	bool m_fastclick; // if true, put the mouse over first button in first tab
 	uint32_t m_best_tab;
@@ -281,7 +284,9 @@
 	m_map(&ib->egbase().map()),
 	m_overlay_manager(*m_map->get_overlay_manager()),
 	m_node(ib->get_sel_pos().node, &(*m_map)[ib->get_sel_pos().node]),
-	m_tabpanel(this, 0, 0, g_gr->get_picture(PicMod_UI, "pics/but1.png")),
+	m_box(this, 0, 0, UI::Box::Vertical),
+	m_buildcostPrev(&m_box, 0, 0, 6, m_plr->tribe(), NULL),
+	m_tabpanel(&m_box, 0, 0, g_gr->get_picture(PicMod_UI, "pics/but1.png")),
 	m_fastclick(true),
 	m_best_tab(0),
 	m_workarea_preview_job_id(Overlay_Manager::Job_Id::Null()),
@@ -289,7 +294,9 @@
 {
 	ib->set_sel_freeze(true);
 
-	set_center_panel(&m_tabpanel);
+	m_box.add(&m_tabpanel, UI::Box::AlignCenter);
+	m_box.add(&m_buildcostPrev, UI::Box::AlignLeft);
+	set_center_panel(&m_box);
 
 	char filename[] = "pics/workarea0cumulative.png";
 	compile_assert(NUMBER_OF_WORKAREA_PICS <= 9);
@@ -831,6 +838,7 @@
 void FieldActionWindow::building_icon_mouse_out
 	(Widelands::Building_Index::value_t)
 {
+	m_buildcostPrev.set_map(NULL);
 	if (m_workarea_preview_job_id) {
 		m_overlay_manager.remove_overlay(m_workarea_preview_job_id);
 		m_workarea_preview_job_id = Overlay_Manager::Job_Id::Null();
@@ -841,6 +849,9 @@
 void FieldActionWindow::building_icon_mouse_in
 	(Widelands::Building_Index::value_t const idx)
 {
+	m_buildcostPrev.set_map
+		(&m_plr->tribe().get_building_descr(Widelands::Building_Index(idx))->buildcost());
+
 	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);

=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc	2012-06-08 22:33:16 +0000
+++ src/wui/waresdisplay.cc	2012-06-25 21:55:27 +0000
@@ -346,3 +346,89 @@
 	//  If you register something twice, it is counted twice. Not my problem.
 	m_warelists.push_back(&wares);
 }
+
+
+/*
+====================================================
+struct BuildcostDisplay
+====================================================
+*/
+
+WaresMapDisplay::WaresMapDisplay
+	(UI::Panel * const parent,
+	 const int32_t x, const int32_t y,
+	 int32_t columns,
+	 Widelands::Tribe_Descr const & tribe,
+	 maptype const * map)
+	:
+	UI::Panel (parent, x, y, 0, 0), m_tribe(tribe), m_columns(columns)
+{
+	set_map(map);
+}
+
+WaresMapDisplay::~WaresMapDisplay()
+{}
+
+void WaresMapDisplay::set_map(maptype const * map) {
+	m_map = map;
+	if (m_map) {
+		int32_t c = m_map->size();
+		set_desired_size
+			((c < m_columns ? c : m_columns) * (WARE_MENU_PIC_WIDTH + 4) + 1,
+			 ((c / m_columns) + (c % m_columns != 0)) * (WARE_MENU_PIC_HEIGHT + 3 + 8) + 1);
+		set_visible(true);
+	} else {
+		set_desired_size(0, 0);
+		set_visible(false);
+	}
+}
+
+void WaresMapDisplay::draw(RenderTarget & dst)
+{
+	if (not m_map)
+		return;
+
+	Point p = Point(2, 2);
+
+	maptype::const_iterator c;
+
+	Widelands::Tribe_Descr::WaresOrder::iterator i;
+	std::vector<Widelands::Ware_Index>::iterator j;
+	Widelands::Tribe_Descr::WaresOrder order = m_tribe.wares_order();
+
+	for (i = order.begin(); i != order.end(); i++)
+		for (j = i->begin(); j != i->end(); j++)
+			if ((c = m_map->find(*j)) != m_map->end()) {
+				//  draw a background
+				const PictureID picid =
+				g_gr->get_picture (PicMod_Game, "pics/ware_list_bg.png");
+				uint32_t w, h;
+				g_gr->get_picture_size(picid, w, h);
+
+				dst.blit(p, picid);
+
+				const Point pos = p + Point((w - WARE_MENU_PIC_WIDTH) / 2, 1);
+				// Draw it
+				dst.blit
+				(pos,
+				 m_tribe.get_ware_descr(c->first)->icon());
+				dst.fill_rect
+				(Rect(pos + Point(0, WARE_MENU_PIC_HEIGHT), WARE_MENU_PIC_WIDTH, 8),
+				 RGBColor(0, 0, 0));
+
+				UI::g_fh->draw_text
+				(dst, UI::TextStyle::ui_ultrasmall(),
+				 p + Point(WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT - 4),
+				 boost::lexical_cast<std::string, uint32_t>(c->second),
+				 UI::Align_Right);
+
+				p.x += (WARE_MENU_PIC_WIDTH + 4);
+				if (p.x >= (m_columns * (WARE_MENU_PIC_WIDTH + 4))) {
+					p.x = 2;
+					p.y += (WARE_MENU_PIC_HEIGHT + 3 + 8);
+				}
+			}
+}
+
+
+

=== modified file 'src/wui/waresdisplay.h'
--- src/wui/waresdisplay.h	2012-02-15 21:25:34 +0000
+++ src/wui/waresdisplay.h	2012-06-25 21:55:27 +0000
@@ -135,4 +135,32 @@
 	vector_type         m_warelists;
 };
 
+
+/**
+ * Displays the build costs of a given building
+ */
+
+struct WaresMapDisplay : public UI::Panel {
+	typedef std::map<Widelands::Ware_Index, uint8_t> maptype;
+
+	WaresMapDisplay
+		(UI::Panel * const parent,
+		 int32_t const x, int32_t const y,
+		 int32_t columns,
+		 Widelands::Tribe_Descr const & tribe,
+		 maptype const * map = NULL);
+
+	virtual ~WaresMapDisplay();
+
+	void set_map(maptype const * map);
+
+private:
+	virtual void draw(RenderTarget &);
+
+private:
+	Widelands::Tribe_Descr const & m_tribe;
+	maptype const * m_map;
+	int32_t m_columns;
+};
+
 #endif


Follow ups