widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #06875
[Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
GunChleoc has proposed merging lp:~widelands-dev/widelands/lua-driven-help into lp:widelands.
Commit message:
The contents of the Tribal Encyclopedia / Editor Help are now defined in Lua files. Removed Readme/Authors/License buttons from in-game/in-editor menu.
Requested reviews:
Widelands Developers (widelands-dev)
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/lua-driven-help/+merge/289782
We can now write arbitrary help chapters in Lua.
When we have merged lp:~widelands-dev/widelands/about, we can improve the contents of the first tab.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/lua-driven-help into lp:widelands.
=== added file 'data/scripting/editor/editor_help.lua'
--- data/scripting/editor/editor_help.lua 1970-01-01 00:00:00 +0000
+++ data/scripting/editor/editor_help.lua 2016-03-22 12:21:57 +0000
@@ -0,0 +1,77 @@
+-- Returns definitions for encyclopedia tabs and their contents for the
+-- Editor Help
+
+
+-- Comparison function used to sort map objects alphabetically
+function compare_by_title(a, b)
+ return a["title"] < b["title"]
+end
+
+-- Returns help entries for all the terrains in the world
+function get_terrains()
+ local result = {}
+ for i, terrain in ipairs(wl.World().terrain_descriptions) do
+ result[i] = {
+ name = terrain.name,
+ title = terrain.descname,
+ icon = terrain.representative_image,
+ script = "scripting/editor/terrain_help.lua",
+ script_parameters = {[1] = terrain.name}
+ }
+ end
+ table.sort(result, compare_by_title)
+ return result
+end
+
+-- Returns help entries for all the trees in the world
+function get_trees()
+ local result = {}
+ local counter = 1
+ for i, immovable in ipairs(wl.World().immovable_descriptions) do
+ if (immovable:has_attribute("tree")) then
+ result[counter] = {
+ name = immovable.name,
+ title = immovable.species,
+ icon = immovable.representative_image,
+ script = "scripting/editor/tree_help.lua",
+ script_parameters = {[1] = immovable.name}
+ }
+ counter = counter + 1
+ end
+ end
+ table.sort(result, compare_by_title)
+ return result
+end
+
+-- Main function
+set_textdomain("widelands")
+return {
+ title = _"Editor Help",
+ tabs = {
+ {
+ name = "general",
+ title = _"General",
+ icon = "images/logos/WL-Editor-32.png",
+ entries = {
+ {
+ name = "intro",
+ title = _"Introduction",
+ script = "txts/editor_readme.lua",
+ script_parameters = {}
+ }
+ }
+ },
+ {
+ name = "terrains",
+ title = _"Terrains",
+ icon = "images/wui/editor/editor_menu_tool_set_terrain.png",
+ entries = get_terrains()
+ },
+ {
+ name = "trees",
+ title = _"Trees",
+ icon = "world/immovables/trees/alder/old/idle_0.png",
+ entries = get_trees()
+ }
+ }
+}
=== modified file 'data/scripting/editor/terrain_help.lua'
--- data/scripting/editor/terrain_help.lua 2016-02-13 13:21:48 +0000
+++ data/scripting/editor/terrain_help.lua 2016-03-22 12:21:57 +0000
@@ -71,6 +71,9 @@
else
result = result .. rt(p(_"No trees will grow here."))
end
- return result
+ return {
+ title = terrain.descname,
+ text = result
+ }
end
}
=== modified file 'data/scripting/editor/tree_help.lua'
--- data/scripting/editor/tree_help.lua 2016-02-13 13:21:48 +0000
+++ data/scripting/editor/tree_help.lua 2016-03-22 12:21:57 +0000
@@ -39,6 +39,9 @@
"<br>" .. ("%2.1f%%"):bformat(100 * v.probability)
) .. spacer()
end
- return result
+ return {
+ title = tree.species,
+ text = result
+ }
end
}
=== modified file 'data/tribes/scripting/help/building_help.lua'
--- data/tribes/scripting/help/building_help.lua 2016-03-02 17:13:06 +0000
+++ data/tribes/scripting/help/building_help.lua 2016-03-22 12:21:57 +0000
@@ -346,10 +346,9 @@
local soldier = wl.Game():get_worker_description(tribe.soldier)
for j, buildcost in ipairs(soldier.buildcost) do
if (buildcost == ware) then
- for k, buildingname in ipairs(tribe.buildings) do
- local warehouse_description = wl.Game():get_building_description(buildingname)
- if (warehouse_description.type_name == "warehouse") then
- outgoing = outgoing .. dependencies({ware, warehouse_description, soldier}, soldier.descname)
+ for k, building in ipairs(tribe.buildings) do
+ if (building.type_name == "warehouse") then
+ outgoing = outgoing .. dependencies({ware, building, soldier}, soldier.descname)
end
end
end
@@ -760,12 +759,15 @@
-- The main function call
return {
- func = function(tribename, building)
+ func = function(tribename, buildingname)
set_textdomain("tribes_encyclopedia")
local tribe = wl.Game():get_tribe_description(tribename)
-- We need to get the building description again, because it will
-- give us a cast to the appropriate subclass.
- local building_description = wl.Game():get_building_description(building.name)
- return building_help(tribe, building_description)
+ local building_description = wl.Game():get_building_description(buildingname)
+ return {
+ title = building_description.descname,
+ text = building_help(tribe, building_description)
+ }
end
}
=== added file 'data/tribes/scripting/help/init.lua'
--- data/tribes/scripting/help/init.lua 1970-01-01 00:00:00 +0000
+++ data/tribes/scripting/help/init.lua 2016-03-22 12:21:57 +0000
@@ -0,0 +1,84 @@
+-- Returns definitions for encyclopedia tabs and their contents for the
+-- Tribal Encyclopedia
+
+-- Comparison function used to sort map objects alphabetically
+function compare_by_title(a, b)
+ return a["title"] < b["title"]
+end
+
+-- Helper function to return all entries of a certain type for the tribe
+function map_object_entries(tribename, script_filename, map_object_table)
+ local result = {}
+ for i, map_object in ipairs(map_object_table) do
+ result[i] = {
+ name = map_object.name,
+ title = map_object.descname,
+ icon = map_object.icon_name,
+ script = script_filename,
+ script_parameters = {[1] = tribename, [2] = map_object.name}
+ }
+ end
+ table.sort(result, compare_by_title)
+ return result
+end
+
+-- Returns help entries for all the buildings that the tribe has
+function building_entries(tribename)
+ local tribe = wl.Game():get_tribe_description(tribename)
+ return map_object_entries(tribename, "tribes/scripting/help/building_help.lua", tribe.buildings)
+end
+
+-- Returns help entries for all the wares that the tribe can use
+function ware_entries(tribename)
+ local tribe = wl.Game():get_tribe_description(tribename)
+ return map_object_entries(tribename, "tribes/scripting/help/ware_help.lua", tribe.wares)
+end
+
+-- Returns help entries for all the workers that the tribe can use
+function worker_entries(tribename)
+ local tribe = wl.Game():get_tribe_description(tribename)
+ return map_object_entries(tribename, "tribes/scripting/help/worker_help.lua", tribe.workers)
+end
+
+-- Main function
+return {
+ func = function(tribename)
+ set_textdomain("tribes_encyclopedia")
+ return {
+ title = _"Tribal Encyclopedia",
+ tabs = {
+ {
+ name = "general",
+ title = _"General",
+ icon = "images/logos/wl-ico-32.png",
+ entries = {
+ {
+ name = "intro",
+ title = _"Introduction",
+ script = "txts/README.lua",
+ script_parameters = {}
+ }
+ }
+ },
+ {
+ name = "wares",
+ title = _"Wares",
+ icon = "images/wui/buildings/menu_tab_wares.png",
+ entries = ware_entries(tribename)
+ },
+ {
+ name = "workers",
+ title = _"Workers",
+ icon = "images/wui/buildings/menu_tab_workers.png",
+ entries = worker_entries(tribename)
+ },
+ {
+ name = "buildings",
+ title = _"Buildings",
+ icon = "images/wui/stats/genstats_nrbuildings.png",
+ entries = building_entries(tribename)
+ },
+ }
+ }
+ end
+}
=== modified file 'data/tribes/scripting/help/ware_help.lua'
--- data/tribes/scripting/help/ware_help.lua 2015-11-05 12:53:49 +0000
+++ data/tribes/scripting/help/ware_help.lua 2016-03-22 12:21:57 +0000
@@ -134,8 +134,7 @@
-- Now collecting the workers that use this ware as a tool
local workers_string = ""
- for i, workername in ipairs(tribe.workers) do
- local worker = wl.Game():get_worker_description(workername)
+ for i, worker in ipairs(tribe.workers) do
local add_this_worker = false
for j, buildcost in ipairs(worker.buildcost) do
if (buildcost ~= nil and buildcost == ware_description.name) then
@@ -165,12 +164,16 @@
return {
- func = function(tribename, ware_description)
+ func = function(tribename, warename)
set_textdomain("tribes_encyclopedia")
local tribe = wl.Game():get_tribe_description(tribename)
+ local ware_description = wl.Game():get_ware_description(warename)
include(ware_description.helptext_script)
- return ware_help_general_string(tribe, ware_description)
- .. ware_help_producers_string(tribe, ware_description)
- .. ware_help_consumers_string(tribe, ware_description)
+ return {
+ title = ware_description.descname,
+ text = ware_help_general_string(tribe, ware_description)
+ .. ware_help_producers_string(tribe, ware_description)
+ .. ware_help_consumers_string(tribe, ware_description)
+ }
end
}
=== modified file 'data/tribes/scripting/help/worker_help.lua'
--- data/tribes/scripting/help/worker_help.lua 2016-02-27 08:43:39 +0000
+++ data/tribes/scripting/help/worker_help.lua 2016-03-22 12:21:57 +0000
@@ -12,8 +12,7 @@
function worker_help_producers_string(tribe, worker_description)
local result = ""
- for i, building_name in ipairs(tribe.buildings) do
- local building = wl.Game():get_building_description(building_name)
+ for i, building in ipairs(tribe.buildings) do
if (building.type_name == "productionsite") then
local recruits_this = false;
for j, output in ipairs(building.output_worker_types) do
@@ -165,9 +164,13 @@
return {
- func = function(tribename, worker_description)
+ func = function(tribename, workername)
set_textdomain("tribes_encyclopedia")
local tribe = wl.Game():get_tribe_description(tribename)
- return worker_help_string(tribe, worker_description)
+ local worker_description = wl.Game():get_worker_description(workername)
+ return {
+ title = worker_description.descname,
+ text = worker_help_string(tribe, worker_description)
+ }
end
}
=== modified file 'data/tribes/scripting/starting_conditions/atlanteans/trading_outpost.lua'
--- data/tribes/scripting/starting_conditions/atlanteans/trading_outpost.lua 2016-03-08 07:40:58 +0000
+++ data/tribes/scripting/starting_conditions/atlanteans/trading_outpost.lua 2016-03-22 12:21:57 +0000
@@ -108,8 +108,8 @@
-- Get all warehouse types
local plr = wl.Game().players[player.number]
local warehouse_types = {}
- for i, building_name in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
- if (wl.Game():get_building_description(building_name).type_name == "warehouse") then
+ for i, building in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
+ if (building.type_name == "warehouse") then
table.insert(warehouse_types, building_name)
end
end
=== modified file 'data/tribes/scripting/starting_conditions/barbarians/trading_outpost.lua'
--- data/tribes/scripting/starting_conditions/barbarians/trading_outpost.lua 2016-03-08 07:40:58 +0000
+++ data/tribes/scripting/starting_conditions/barbarians/trading_outpost.lua 2016-03-22 12:21:57 +0000
@@ -99,8 +99,8 @@
-- Get all warehouse types
local plr = wl.Game().players[player.number]
local warehouse_types = {}
- for i, building_name in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
- if (wl.Game():get_building_description(building_name).type_name == "warehouse") then
+ for i, building in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
+ if (building.type_name == "warehouse") then
table.insert(warehouse_types, building_name)
end
end
=== modified file 'data/tribes/scripting/starting_conditions/empire/trading_outpost.lua'
--- data/tribes/scripting/starting_conditions/empire/trading_outpost.lua 2016-03-08 07:40:58 +0000
+++ data/tribes/scripting/starting_conditions/empire/trading_outpost.lua 2016-03-22 12:21:57 +0000
@@ -105,8 +105,8 @@
-- Get all warehouse types
local plr = wl.Game().players[player.number]
local warehouse_types = {}
- for i, building_name in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
- if (wl.Game():get_building_description(building_name).type_name == "warehouse") then
+ for i, building in ipairs(wl.Game():get_tribe_description(plr.tribe_name).buildings) do
+ if (building.type_name == "warehouse") then
table.insert(warehouse_types, building_name)
end
end
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt 2016-01-24 11:11:54 +0000
+++ src/editor/CMakeLists.txt 2016-03-22 12:21:57 +0000
@@ -103,7 +103,6 @@
scripting_lua_interface
scripting_lua_table
ui_basic
- ui_fsmenu
widelands_ball_of_mud
wui
wui_common
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc 2016-03-19 11:47:00 +0000
+++ src/editor/editorinteractive.cc 2016-03-22 12:21:57 +0000
@@ -370,7 +370,7 @@
if (helpmenu_.window)
delete helpmenu_.window;
else
- new EditorHelp(*this, helpmenu_);
+ new EditorHelp(*this, helpmenu_, &egbase().lua());
}
=== modified file 'src/editor/ui_menus/editor_help.cc'
--- src/editor/ui_menus/editor_help.cc 2016-02-13 11:30:01 +0000
+++ src/editor/ui_menus/editor_help.cc 2016-03-22 12:21:57 +0000
@@ -19,206 +19,30 @@
#include "editor/ui_menus/editor_help.h"
-#include <algorithm>
-#include <map>
+
#include <memory>
-#include <string>
-#include <vector>
#include <boost/format.hpp>
#include "base/i18n.h"
#include "editor/editorinteractive.h"
-#include "graphic/graphic.h"
-#include "graphic/texture.h"
-#include "io/filesystem/layered_filesystem.h"
-#include "logic/map_objects/world/editor_category.h"
-#include "logic/map_objects/world/terrain_description.h"
-#include "logic/map_objects/world/world.h"
+#include "scripting/lua_coroutine.h"
#include "scripting/lua_interface.h"
#include "scripting/lua_table.h"
-
-namespace {
-
-#define WINDOW_WIDTH std::min(700, g_gr->get_xres() - 40)
-#define WINDOW_HEIGHT std::min(550, g_gr->get_yres() - 40)
-
-constexpr int kPadding = 5;
-constexpr int kTabHeight = 35;
-
-const std::string heading(const std::string& text) {
- return ((boost::format("<rt><p font-size=18 font-weight=bold font-color=D1D1D1>"
- "%s<br></p><p font-size=8> <br></p></rt>") %
- text).str());
-}
-
-} // namespace
-
-inline EditorInteractive& EditorHelp::eia() const {
- return dynamic_cast<EditorInteractive&>(*get_parent());
-}
-
-EditorHelp::EditorHelp(EditorInteractive& parent, UI::UniqueWindow::Registry& registry)
- : UI::UniqueWindow(&parent, "encyclopedia", ®istry, WINDOW_WIDTH, WINDOW_HEIGHT, _("Help")),
- tabs_(this, 0, 0, nullptr) {
-
- const int contents_height = WINDOW_HEIGHT - kTabHeight - 2 * kPadding;
- const int contents_width = WINDOW_WIDTH / 2 - 1.5 * kPadding;
-
- std::vector<std::unique_ptr<HelpTab>> tab_definitions;
-
- tab_definitions.push_back(
- std::unique_ptr<HelpTab>(new HelpTab("terrains",
- "images/wui/editor/editor_menu_tool_set_terrain.png",
- _("Terrains"),
- "scripting/editor/terrain_help.lua",
- HelpEntry::Type::kTerrain)));
-
- tab_definitions.push_back(
- std::unique_ptr<HelpTab>(new HelpTab("trees",
- "world/immovables/trees/alder/old/idle_0.png",
- _("Trees"),
- "scripting/editor/tree_help.lua",
- HelpEntry::Type::kTree)));
-
- for (const auto& tab : tab_definitions) {
- // Make sure that all paths exist
- if (!g_fs->file_exists(tab->script_path)) {
- throw wexception("Script path %s for tab %s does not exist!",
- tab->script_path.c_str(),
- tab->key.c_str());
- }
- if (!g_fs->file_exists(tab->image_filename)) {
- throw wexception("Image path %s for tab %s does not exist!",
- tab->image_filename.c_str(),
- tab->key.c_str());
- }
-
- wrapper_boxes_.insert(std::make_pair(
- tab->key, std::unique_ptr<UI::Box>(new UI::Box(&tabs_, 0, 0, UI::Box::Horizontal))));
-
- boxes_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::Box>(new UI::Box(
- wrapper_boxes_.at(tab->key).get(), 0, 0, UI::Box::Horizontal))));
-
- lists_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>(
- new UI::Listselect<Widelands::DescriptionIndex>(
- boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
- lists_.at(tab->key)->selected.connect(
- boost::bind(&EditorHelp::entry_selected, this, tab->key, tab->script_path, tab->type));
-
- contents_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::MultilineTextarea>(new UI::MultilineTextarea(
- boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
-
- boxes_.at(tab->key)->add(lists_.at(tab->key).get(), UI::Align::kLeft);
- boxes_.at(tab->key)->add_space(kPadding);
- boxes_.at(tab->key)->add(contents_.at(tab->key).get(), UI::Align::kLeft);
-
- wrapper_boxes_.at(tab->key)->add_space(kPadding);
- wrapper_boxes_.at(tab->key)->add(boxes_.at(tab->key).get(), UI::Align::kLeft);
-
- tabs_.add("editor_help_" + tab->key,
- g_gr->images().get(tab->image_filename),
- wrapper_boxes_.at(tab->key).get(),
- tab->tooltip);
- }
- tabs_.set_size(WINDOW_WIDTH, WINDOW_HEIGHT);
-
- fill_terrains();
- fill_trees();
-
- if (get_usedefaultpos()) {
- center_to_parent();
- }
-}
-
-void EditorHelp::fill_entries(const char* key, std::vector<HelpEntry>* entries) {
- std::sort(entries->begin(), entries->end());
- for (uint32_t i = 0; i < entries->size(); i++) {
- HelpEntry cur = (*entries)[i];
- lists_.at(key)->add(cur.descname, cur.index, cur.icon);
- }
- lists_.at(key)->select(0);
-}
-
-void EditorHelp::fill_terrains() {
- const Widelands::World& world = eia().egbase().world();
- std::vector<HelpEntry> entries;
-
- for (Widelands::DescriptionIndex i = 0; i < world.terrains().size(); ++i) {
- const Widelands::TerrainDescription& terrain = world.terrain_descr(i);
- upcast(Image const, icon, &terrain.get_texture(0));
- /** TRANSLATORS: Terrain name + editor category, e.g. Steppe (Summer) */
- HelpEntry entry(i, (boost::format(_("%1% (%2%)"))
- % terrain.descname().c_str()
- % terrain.editor_category()->descname()).str(), icon);
- entries.push_back(entry);
- }
- fill_entries("terrains", &entries);
-}
-
-void EditorHelp::fill_trees() {
- const Widelands::World& world = eia().egbase().world();
- std::vector<HelpEntry> entries;
-
- for (Widelands::DescriptionIndex i = 0; i < world.get_nr_immovables(); ++i) {
- const Widelands::ImmovableDescr* immovable = world.get_immovable_descr(i);
- uint32_t attribute_id = immovable->get_attribute_id("tree");
- if (immovable->has_attribute(attribute_id)) {
- const Image* icon = immovable->representative_image();
- HelpEntry entry(i, immovable->species(), icon);
- entries.push_back(entry);
- }
- }
- fill_entries("trees", &entries);
-}
-
-void EditorHelp::entry_selected(const std::string& key,
- const std::string& script_path,
- const HelpEntry::Type& type) {
+#include "ui_basic/messagebox.h"
+
+EditorHelp::EditorHelp(EditorInteractive& parent, UI::UniqueWindow::Registry& registry, LuaInterface* const lua)
+ : EncyclopediaWindow(parent, registry, lua)
+{
try {
- std::unique_ptr<LuaTable> table(eia().egbase().lua().run_script(script_path));
- std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func"));
-
- std::string descname = "";
-
- switch (type) {
- case (HelpEntry::Type::kTerrain): {
- const Widelands::TerrainDescription& descr =
- eia().egbase().world().terrain_descr(lists_.at(key)->get_selected());
- /** TRANSLATORS: Terrain name + editor category, e.g. Steppe (Summer) */
- descname = (boost::format(_("%1% (%2%)"))
- % descr.descname().c_str()
- % descr.editor_category()->descname()).str();
- cr->push_arg(descr.name());
- break;
- }
- case (HelpEntry::Type::kTree): {
- const Widelands::ImmovableDescr* descr =
- eia().egbase().world().get_immovable_descr(lists_.at(key)->get_selected());
- descname = descr->species();
- cr->push_arg(descr->name());
- break;
- }
- default:
- throw wexception("EditorHelp: No Type defined for tab.");
- }
-
- cr->resume();
- const std::string help_text = cr->pop_string();
-
- // We add the heading here instead of in Lua, so that the content can be
- // reused in a standalone window that will have the heading as a window
- // title.
- contents_.at(key)->set_text((boost::format("%s%s") % heading(descname) % help_text).str());
-
+ init(parent, lua_->run_script("scripting/editor/editor_help.lua"));
} catch (LuaError& err) {
- contents_.at(key)->set_text(err.what());
+ log("Error loading script for editor help:\n%s\n", err.what());
+ UI::WLMessageBox wmb(
+ &parent,
+ _("Error!"),
+ (boost::format("Error loading script for editor help:\n%s") % err.what()).str(),
+ UI::WLMessageBox::MBoxType::kOk);
+ wmb.run<UI::Panel::Returncodes>();
}
- contents_.at(key)->scroll_to_top();
}
=== modified file 'src/editor/ui_menus/editor_help.h'
--- src/editor/ui_menus/editor_help.h 2016-03-07 19:06:19 +0000
+++ src/editor/ui_menus/editor_help.h 2016-03-22 12:21:57 +0000
@@ -20,87 +20,14 @@
#ifndef WL_EDITOR_UI_MENUS_EDITOR_HELP_H
#define WL_EDITOR_UI_MENUS_EDITOR_HELP_H
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "logic/map_objects/map_object.h"
-#include "ui_basic/box.h"
-#include "ui_basic/listselect.h"
-#include "ui_basic/multilinetextarea.h"
-#include "ui_basic/table.h"
-#include "ui_basic/tabpanel.h"
+#include "scripting/lua_interface.h"
+#include "ui_basic/encyclopedia_window.h"
#include "ui_basic/unique_window.h"
-#include "ui_basic/window.h"
class EditorInteractive;
-struct EditorHelp : public UI::UniqueWindow {
- EditorHelp(EditorInteractive&, UI::UniqueWindow::Registry&);
-
-private:
- struct HelpEntry {
- enum class Type {
- kTerrain,
- kTree
- };
-
- HelpEntry(const Widelands::DescriptionIndex init_index,
- const std::string& init_descname,
- const Image* init_icon)
- : index(init_index), descname(init_descname), icon(init_icon) {
- }
- Widelands::DescriptionIndex index;
- std::string descname;
- const Image* icon;
-
- bool operator<(const HelpEntry& other) const {
- return descname < other.descname;
- }
- };
-
- struct HelpTab {
- HelpTab(const std::string& _key,
- const std::string& _image_filename,
- const std::string& _tooltip,
- const std::string& _script_path,
- const EditorHelp::HelpEntry::Type _type)
- : key(_key),
- image_filename(_image_filename),
- tooltip(_tooltip),
- script_path(_script_path),
- type(_type) {
- }
- const std::string key;
- const std::string image_filename;
- const std::string tooltip;
- const std::string script_path;
- const EditorHelp::HelpEntry::Type type;
- };
-
- EditorInteractive& eia() const;
-
- // Fill table of contents
- void fill_entries(const char* key, std::vector<HelpEntry>* entries);
- void fill_terrains();
- void fill_trees();
-
- // Update contents when an entry is selected
- void entry_selected(const std::string& key,
- const std::string& script_path,
- const HelpEntry::Type& type);
-
- // UI elements
- UI::TabPanel tabs_;
-
- // Wrapper boxes so we can add some padding
- std::map<std::string, std::unique_ptr<UI::Box>> wrapper_boxes_;
- // Main contents boxes for each tab
- std::map<std::string, std::unique_ptr<UI::Box>> boxes_;
- // A tab's table of contents
- std::map<std::string, std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>> lists_;
- // The contents shown when an entry is selected in a tab
- std::map<std::string, std::unique_ptr<UI::MultilineTextarea>> contents_;
+struct EditorHelp : public UI::EncyclopediaWindow {
+ EditorHelp(EditorInteractive&, UI::UniqueWindow::Registry&, LuaInterface* const lua);
};
#endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_HELP_H
=== modified file 'src/editor/ui_menus/editor_main_menu.cc'
--- src/editor/ui_menus/editor_main_menu.cc 2016-02-18 18:27:52 +0000
+++ src/editor/ui_menus/editor_main_menu.cc 2016-03-22 12:21:57 +0000
@@ -26,7 +26,6 @@
#include "editor/ui_menus/editor_main_menu_new_map.h"
#include "editor/ui_menus/editor_main_menu_random_map.h"
#include "editor/ui_menus/editor_main_menu_save_map.h"
-#include "ui_fsmenu/fileview.h"
// TODO(unknown): these should be defined globally for the whole UI
#define width 200
@@ -71,11 +70,6 @@
0, 0, width, 0,
g_gr->images().get("images/ui_basic/but1.png"),
_("Map Options")),
- button_view_readme_
- (&box_, "readme",
- 0, 0, width, 0,
- g_gr->images().get("images/ui_basic/but1.png"),
- _("View Readme")),
button_exit_editor_
(&box_, "exit",
0, 0, width, 0,
@@ -87,9 +81,8 @@
box_.add(&button_load_map_, UI::Align::kHCenter);
box_.add(&button_save_map_, UI::Align::kHCenter);
box_.add(&button_map_options_, UI::Align::kHCenter);
- box_.add(&button_view_readme_, UI::Align::kHCenter);
box_.add(&button_exit_editor_, UI::Align::kHCenter);
- box_.set_size(width, 7 * button_new_map_.get_h()+ 6 * vspacing);
+ box_.set_size(width, 6 * button_new_map_.get_h()+ 5 * vspacing);
set_inner_size(get_inner_w(), box_.get_h() + 2 * margin);
button_new_map_.sigclicked.connect(boost::bind(&EditorMainMenu::new_map_btn, this));
@@ -97,13 +90,6 @@
button_load_map_.sigclicked.connect(boost::bind(&EditorMainMenu::load_btn, this));
button_save_map_.sigclicked.connect(boost::bind(&EditorMainMenu::save_btn, this));
button_map_options_.sigclicked.connect(boost::bind(&EditorMainMenu::map_options_btn, this));
-
- window_readme_.open_window = [this] {
- fileview_window(eia(), window_readme_, "txts/editor_readme.lua");
- };
- button_view_readme_.sigclicked.connect(
- boost::bind(&UI::UniqueWindow::Registry::toggle, window_readme_));
-
button_exit_editor_.sigclicked.connect(boost::bind(&EditorMainMenu::exit_btn, this));
// Put in the default position, if necessary
=== modified file 'src/editor/ui_menus/editor_main_menu.h'
--- src/editor/ui_menus/editor_main_menu.h 2016-01-16 12:55:14 +0000
+++ src/editor/ui_menus/editor_main_menu.h 2016-03-22 12:21:57 +0000
@@ -40,11 +40,8 @@
UI::Button button_load_map_;
UI::Button button_save_map_;
UI::Button button_map_options_;
- UI::Button button_view_readme_;
UI::Button button_exit_editor_;
- UI::UniqueWindow::Registry window_readme_;
-
void exit_btn ();
void load_btn ();
void save_btn ();
=== modified file 'src/scripting/lua_coroutine.cc'
--- src/scripting/lua_coroutine.cc 2016-02-12 16:58:41 +0000
+++ src/scripting/lua_coroutine.cc 2016-03-22 12:21:57 +0000
@@ -19,6 +19,8 @@
#include "scripting/lua_coroutine.h"
+#include <memory>
+
#include "io/fileread.h"
#include "io/filewrite.h"
#include "scripting/lua_errors.h"
@@ -99,24 +101,6 @@
++ninput_args_;
}
-void LuaCoroutine::push_arg(const Widelands::BuildingDescr* building_descr) {
- assert(building_descr != nullptr);
- to_lua<LuaMaps::LuaBuildingDescription>(lua_state_, new LuaMaps::LuaBuildingDescription(building_descr));
- ++ninput_args_;
-}
-
-void LuaCoroutine::push_arg(const Widelands::WareDescr* ware_descr) {
- assert(ware_descr != nullptr);
- to_lua<LuaMaps::LuaWareDescription>(lua_state_, new LuaMaps::LuaWareDescription(ware_descr));
- ++ninput_args_;
-}
-
-void LuaCoroutine::push_arg(const Widelands::WorkerDescr* worker_descr) {
- assert(worker_descr != nullptr);
- to_lua<LuaMaps::LuaWorkerDescription>(lua_state_, new LuaMaps::LuaWorkerDescription(worker_descr));
- ++ninput_args_;
-}
-
void LuaCoroutine::push_arg(const std::string& string) {
assert(!string.empty());
lua_pushstring(lua_state_, string);
@@ -149,6 +133,17 @@
return return_value;
}
+std::unique_ptr<LuaTable> LuaCoroutine::pop_table() {
+ std::unique_ptr<LuaTable> result(nullptr);
+ if (!nreturn_values_) {
+ return result;
+ }
+ result.reset(new LuaTable(lua_state_));
+ lua_pop(lua_state_, 1);
+ --nreturn_values_;
+ return result;
+}
+
constexpr uint8_t kCoroutineDataPacketVersion = 3;
void LuaCoroutine::write(FileWrite& fw) {
fw.unsigned_8(kCoroutineDataPacketVersion);
=== modified file 'src/scripting/lua_coroutine.h'
--- src/scripting/lua_coroutine.h 2016-02-12 16:58:41 +0000
+++ src/scripting/lua_coroutine.h 2016-03-22 12:21:57 +0000
@@ -20,6 +20,7 @@
#ifndef WL_SCRIPTING_LUA_COROUTINE_H
#define WL_SCRIPTING_LUA_COROUTINE_H
+#include <memory>
#include <string>
#include <stdint.h>
@@ -28,6 +29,7 @@
class FileRead;
class FileWrite;
+class LuaTable;
namespace Widelands {
class Player;
@@ -62,14 +64,12 @@
// in hooks.
void push_arg(const Widelands::Player*);
void push_arg(const Widelands::Coords&);
- void push_arg(const Widelands::BuildingDescr*);
- void push_arg(const Widelands::WareDescr*);
- void push_arg(const Widelands::WorkerDescr*);
void push_arg(const std::string&);
// Accesses the returned values from the run of the coroutine.
uint32_t pop_uint32();
std::string pop_string();
+ std::unique_ptr<LuaTable> pop_table();
private:
friend class LuaGameInterface;
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc 2016-03-19 12:51:22 +0000
+++ src/scripting/lua_map.cc 2016-03-22 12:21:57 +0000
@@ -1108,15 +1108,16 @@
/* RST
.. attribute:: buildings
- (RO) an array of :class:`string` with the names of all the buildings that the tribe can use
+ (RO) an array of :class:`LuaBuildingDescription` with all the buildings that the tribe can use,
+ casted to their appropriate subclasses.
*/
-
int LuaTribeDescription::get_buildings(lua_State * L) {
+ const TribeDescr& tribe = *get();
lua_newtable(L);
int counter = 0;
- for (DescriptionIndex building : get()->buildings()) {
+ for (DescriptionIndex building : tribe.buildings()) {
lua_pushinteger(L, ++counter);
- lua_pushstring(L, get_egbase(L).tribes().get_building_descr(building)->name());
+ upcasted_map_object_descr_to_lua(L, tribe.get_building_descr(building));
lua_settable(L, -3);
}
return 1;
@@ -1230,15 +1231,15 @@
/* RST
.. attribute:: wares
- (RO) an array of :class:`string` with the names of all the wares that the tribe uses
+ (RO) an array of :class:`LuaWareDescription` with all the wares that the tribe can use.
*/
-
int LuaTribeDescription::get_wares(lua_State * L) {
+ const TribeDescr& tribe = *get();
lua_newtable(L);
int counter = 0;
- for (DescriptionIndex ware : get()->wares()) {
+ for (DescriptionIndex ware : tribe.wares()) {
lua_pushinteger(L, ++counter);
- lua_pushstring(L, get_egbase(L).tribes().get_ware_descr(ware)->name());
+ to_lua<LuaWareDescription>(L, new LuaWareDescription(tribe.get_ware_descr(ware)));
lua_settable(L, -3);
}
return 1;
@@ -1247,15 +1248,16 @@
/* RST
.. attribute:: workers
- (RO) an array of :class:`string` with the names of all the workers that the tribe can use
+ (RO) an array of :class:`LuaWorkerDescription` with all the workers that the tribe can use,
+ casted to their appropriate subclasses.
*/
-
int LuaTribeDescription::get_workers(lua_State * L) {
+ const TribeDescr& tribe = *get();
lua_newtable(L);
int counter = 0;
- for (DescriptionIndex worker : get()->workers()) {
+ for (DescriptionIndex worker : tribe.workers()) {
lua_pushinteger(L, ++counter);
- lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(worker)->name());
+ upcasted_map_object_descr_to_lua(L, tribe.get_worker_descr(worker));
lua_settable(L, -3);
}
return 1;
=== modified file 'src/ui_basic/CMakeLists.txt'
--- src/ui_basic/CMakeLists.txt 2015-11-28 11:45:40 +0000
+++ src/ui_basic/CMakeLists.txt 2016-03-22 12:21:57 +0000
@@ -8,6 +8,8 @@
checkbox.h
editbox.cc
editbox.h
+ encyclopedia_window.cc
+ encyclopedia_window.h
icon.cc
icon.h
icongrid.cc
@@ -60,6 +62,9 @@
graphic_text_layout
io_filesystem
profile
+ scripting_coroutine
+ scripting_lua_interface
+ scripting_lua_table
sound
widelands_ball_of_mud
)
=== renamed file 'src/wui/encyclopedia_window.cc' => 'src/ui_basic/encyclopedia_window.cc'
--- src/wui/encyclopedia_window.cc 2016-02-14 14:09:29 +0000
+++ src/ui_basic/encyclopedia_window.cc 2016-03-22 12:21:57 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002-2016 by the Widelands Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,14 +17,10 @@
*
*/
-#include "wui/encyclopedia_window.h"
+#include "ui_basic/encyclopedia_window.h"
-#include <algorithm>
-#include <cstring>
#include <map>
#include <memory>
-#include <set>
-#include <string>
#include <vector>
#include <boost/format.hpp>
@@ -32,15 +28,10 @@
#include "base/i18n.h"
#include "graphic/graphic.h"
#include "io/filesystem/layered_filesystem.h"
-#include "logic/map_objects/tribes/building.h"
#include "logic/map_objects/tribes/tribe_descr.h"
-#include "logic/map_objects/tribes/tribes.h"
-#include "logic/map_objects/tribes/ware_descr.h"
-#include "logic/map_objects/tribes/worker_descr.h"
-#include "logic/player.h"
-#include "scripting/lua_interface.h"
-#include "scripting/lua_table.h"
-#include "wui/interactive_player.h"
+#include "scripting/lua_coroutine.h"
+#include "ui_basic/messagebox.h"
+#include "wui/interactive_base.h"
namespace {
@@ -50,25 +41,6 @@
constexpr int kPadding = 5;
constexpr int kTabHeight = 35;
-struct EncyclopediaTab {
- EncyclopediaTab(const std::string& init_key,
- const std::string& init_image_filename,
- const std::string& init_tooltip,
- const std::string& init_script_path,
- const Widelands::MapObjectType init_type)
- : key(init_key),
- image_filename(init_image_filename),
- tooltip(init_tooltip),
- script_path(init_script_path),
- type(init_type) {
- }
- const std::string key;
- const std::string image_filename;
- const std::string tooltip;
- const std::string script_path;
- const Widelands::MapObjectType type;
-};
-
const std::string heading(const std::string& text) {
return ((boost::format("<rt><p font-size=18 font-weight=bold font-color=D1D1D1>"
"%s<br></p><p font-size=8> <br></p></rt>") %
@@ -77,204 +49,142 @@
} // namespace
-inline InteractivePlayer& EncyclopediaWindow::iaplayer() const {
- return dynamic_cast<InteractivePlayer&>(*get_parent());
-}
+namespace UI {
-EncyclopediaWindow::EncyclopediaWindow(InteractivePlayer& parent, UI::UniqueWindow::Registry& registry)
+EncyclopediaWindow::EncyclopediaWindow(InteractiveBase& parent, UI::UniqueWindow::Registry& registry, LuaInterface* const lua)
: UI::UniqueWindow(
- &parent, "encyclopedia", ®istry, WINDOW_WIDTH, WINDOW_HEIGHT, _("Tribal Encyclopedia")),
- tabs_(this, 0, 0, nullptr) {
+ &parent, "encyclopedia", ®istry, WINDOW_WIDTH, WINDOW_HEIGHT, ""),
+ lua_(lua),
+ tabs_(this, 0, 0, nullptr)
+ {}
+
+void EncyclopediaWindow::init(InteractiveBase& parent, std::unique_ptr<LuaTable> table) {
const int contents_height = WINDOW_HEIGHT - kTabHeight - 2 * kPadding;
const int contents_width = WINDOW_WIDTH / 2 - 1.5 * kPadding;
- std::vector<std::unique_ptr<EncyclopediaTab>> tab_definitions;
-
- tab_definitions.push_back(
- std::unique_ptr<EncyclopediaTab>(new EncyclopediaTab("wares",
- "images/wui/buildings/menu_tab_wares.png",
- _("Wares"),
- "tribes/scripting/help/ware_help.lua",
- Widelands::MapObjectType::WARE)));
-
- tab_definitions.push_back(
- std::unique_ptr<EncyclopediaTab>(new EncyclopediaTab("workers",
- "images/wui/buildings/menu_tab_workers.png",
- _("Workers"),
- "tribes/scripting/help/worker_help.lua",
- Widelands::MapObjectType::WORKER)));
-
- tab_definitions.push_back(std::unique_ptr<EncyclopediaTab>(
- new EncyclopediaTab("buildings",
- "images/wui/stats/genstats_nrbuildings.png",
- _("Buildings"),
- "tribes/scripting/help/building_help.lua",
- Widelands::MapObjectType::BUILDING)));
-
- for (const auto& tab : tab_definitions) {
- // Make sure that all paths exist
- if (!g_fs->file_exists(tab->script_path)) {
- throw wexception("Script path %s for tab %s does not exist!",
- tab->script_path.c_str(),
- tab->key.c_str());
- }
- if (!g_fs->file_exists(tab->image_filename)) {
- throw wexception("Image path %s for tab %s does not exist!",
- tab->image_filename.c_str(),
- tab->key.c_str());
- }
-
- wrapper_boxes_.insert(std::make_pair(
- tab->key, std::unique_ptr<UI::Box>(new UI::Box(&tabs_, 0, 0, UI::Box::Horizontal))));
-
- boxes_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::Box>(new UI::Box(
- wrapper_boxes_.at(tab->key).get(), 0, 0, UI::Box::Horizontal))));
-
- lists_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>(
- new UI::Listselect<Widelands::DescriptionIndex>(
- boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
- lists_.at(tab->key)->selected.connect(boost::bind(
- &EncyclopediaWindow::entry_selected, this, tab->key, tab->script_path, tab->type));
-
- contents_.insert(
- std::make_pair(tab->key,
- std::unique_ptr<UI::MultilineTextarea>(new UI::MultilineTextarea(
- boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
-
- boxes_.at(tab->key)->add(lists_.at(tab->key).get(), UI::Align::kLeft);
- boxes_.at(tab->key)->add_space(kPadding);
- boxes_.at(tab->key)->add(contents_.at(tab->key).get(), UI::Align::kLeft);
-
- wrapper_boxes_.at(tab->key)->add_space(kPadding);
- wrapper_boxes_.at(tab->key)->add(boxes_.at(tab->key).get(), UI::Align::kLeft);
-
- tabs_.add("encyclopedia_" + tab->key,
- g_gr->images().get(tab->image_filename),
- wrapper_boxes_.at(tab->key).get(),
- tab->tooltip);
- }
+ try {
+ set_title(table->get_string("title"));
+
+ // Read tab definitions
+ std::unique_ptr<LuaTable> tabs_table = table->get_table("tabs");
+ for (const auto& tab_table : tabs_table->array_entries<std::unique_ptr<LuaTable>>()) {
+ const std::string tab_name = tab_table->get_string("name");
+ const std::string tab_icon = tab_table->has_key("icon") ? tab_table->get_string("icon") : "";
+ const std::string tab_title = tab_table->get_string("title");
+
+ wrapper_boxes_.insert(std::make_pair(
+ tab_name, std::unique_ptr<UI::Box>(new UI::Box(&tabs_, 0, 0, UI::Box::Horizontal))));
+
+ boxes_.insert(
+ std::make_pair(tab_name,
+ std::unique_ptr<UI::Box>(new UI::Box(
+ wrapper_boxes_.at(tab_name).get(), 0, 0, UI::Box::Horizontal))));
+
+ lists_.insert(
+ std::make_pair(tab_name,
+ std::unique_ptr<UI::Listselect<EncyclopediaEntry>>(
+ new UI::Listselect<EncyclopediaEntry>(
+ boxes_.at(tab_name).get(), 0, 0, contents_width, contents_height))));
+ lists_.at(tab_name)->selected.connect(boost::bind(&EncyclopediaWindow::entry_selected, this, tab_name));
+
+ contents_.insert(
+ std::make_pair(tab_name,
+ std::unique_ptr<UI::MultilineTextarea>(new UI::MultilineTextarea(
+ boxes_.at(tab_name).get(), 0, 0, contents_width, contents_height))));
+
+ boxes_.at(tab_name)->add(lists_.at(tab_name).get(), UI::Align::kLeft);
+ boxes_.at(tab_name)->add_space(kPadding);
+ boxes_.at(tab_name)->add(contents_.at(tab_name).get(), UI::Align::kLeft);
+
+ wrapper_boxes_.at(tab_name)->add_space(kPadding);
+ wrapper_boxes_.at(tab_name)->add(boxes_.at(tab_name).get(), UI::Align::kLeft);
+
+ if (tab_icon.empty()) {
+ tabs_.add("encyclopedia_" + tab_name,
+ tab_title,
+ wrapper_boxes_.at(tab_name).get());
+ } else if (g_fs->file_exists(tab_icon)) {
+ tabs_.add("encyclopedia_" + tab_name,
+ g_gr->images().get(tab_icon),
+ wrapper_boxes_.at(tab_name).get(),
+ tab_title);
+ } else {
+ throw wexception("Icon path '%s' for tab '%s' does not exist!",
+ tab_icon.c_str(),
+ tab_name.c_str());
+ }
+
+ // Now fill the lists
+ std::unique_ptr<LuaTable> entries_table = tab_table->get_table("entries");
+ for (const auto& entry_table : entries_table->array_entries<std::unique_ptr<LuaTable>>()) {
+ const std::string entry_name = entry_table->get_string("name");
+ const std::string entry_title = entry_table->get_string("title");
+ const std::string entry_icon = entry_table->has_key("icon") ? entry_table->get_string("icon") : "";
+ const std::string entry_script = entry_table->get_string("script");
+
+ // Make sure that all paths exist
+ if (!g_fs->file_exists(entry_script)) {
+ throw wexception("Script path %s for entry %s does not exist!",
+ entry_script.c_str(),
+ entry_name.c_str());
+ }
+
+ EncyclopediaEntry entry(entry_script, entry_table->get_table("script_parameters")->array_entries<std::string>());
+
+ if (entry_icon.empty()) {
+ lists_.at(tab_name)->add(entry_title, entry);
+ } else if (g_fs->file_exists(entry_icon)) {
+ lists_.at(tab_name)->add(entry_title, entry, g_gr->images().get(entry_icon));
+ } else {
+ throw wexception("Icon path '%s' for tab entry '%s' does not exist!",
+ entry_icon.c_str(),
+ entry_name.c_str());
+ }
+ }
+ }
+ } catch (WException& err) {
+ log("Error loading script for encyclopedia:\n%s\n", err.what());
+ UI::WLMessageBox wmb(
+ &parent,
+ _("Error!"),
+ (boost::format("Error loading script for encyclopedia:\n%s") % err.what()).str(),
+ UI::WLMessageBox::MBoxType::kOk);
+ wmb.run<UI::Panel::Returncodes>();
+ }
+
+ for (const auto& list : lists_) {
+ if (!(list.second->empty())) {
+ list.second->select(0);
+ }
+ }
+
tabs_.set_size(WINDOW_WIDTH, WINDOW_HEIGHT);
- fill_buildings();
- fill_wares();
- fill_workers();
-
if (get_usedefaultpos()) {
center_to_parent();
}
}
-void EncyclopediaWindow::fill_entries(const char* key, std::vector<EncyclopediaEntry>* entries) {
- std::sort(entries->begin(), entries->end());
- for (uint32_t i = 0; i < entries->size(); i++) {
- EncyclopediaEntry cur = (*entries)[i];
- lists_.at(key)->add(cur.descname, cur.index, cur.icon);
- }
- lists_.at(key)->select(0);
-}
-
-void EncyclopediaWindow::fill_buildings() {
- const Widelands::Tribes& tribes = iaplayer().egbase().tribes();
- const Widelands::TribeDescr& tribe = iaplayer().player().tribe();
- std::vector<EncyclopediaEntry> entries;
-
- for (Widelands::DescriptionIndex i = 0; i < tribes.nrbuildings(); ++i) {
- const Widelands::BuildingDescr* building = tribes.get_building_descr(i);
- if (tribe.has_building(i) || building->type() == Widelands::MapObjectType::MILITARYSITE) {
- EncyclopediaEntry entry(i, building->descname(), building->icon());
- entries.push_back(entry);
- }
- }
- fill_entries("buildings", &entries);
-}
-
-void EncyclopediaWindow::fill_wares() {
- const Widelands::TribeDescr& tribe = iaplayer().player().tribe();
- std::vector<EncyclopediaEntry> entries;
-
- for (const Widelands::DescriptionIndex& i : tribe.wares()) {
- const Widelands::WareDescr* ware = tribe.get_ware_descr(i);
- EncyclopediaEntry entry(i, ware->descname(), ware->icon());
- entries.push_back(entry);
- }
- fill_entries("wares", &entries);
-}
-
-void EncyclopediaWindow::fill_workers() {
- const Widelands::TribeDescr& tribe = iaplayer().player().tribe();
- std::vector<EncyclopediaEntry> entries;
-
- for (const Widelands::DescriptionIndex& i : tribe.workers()) {
- const Widelands::WorkerDescr* worker = tribe.get_worker_descr(i);
- EncyclopediaEntry entry(i, worker->descname(), worker->icon());
- entries.push_back(entry);
- }
- fill_entries("workers", &entries);
-}
-
-void EncyclopediaWindow::entry_selected(const std::string& key,
- const std::string& script_path,
- const Widelands::MapObjectType& type) {
- const Widelands::TribeDescr& tribe = iaplayer().player().tribe();
+void EncyclopediaWindow::entry_selected(const std::string& tab_name) {
+ const EncyclopediaEntry& entry = lists_.at(tab_name)->get_selected();
try {
- std::unique_ptr<LuaTable> table(iaplayer().egbase().lua().run_script(script_path));
- std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func"));
- cr->push_arg(tribe.name());
-
- std::string descname = "";
-
- switch (type) {
- case (Widelands::MapObjectType::BUILDING):
- case (Widelands::MapObjectType::CONSTRUCTIONSITE):
- case (Widelands::MapObjectType::DISMANTLESITE):
- case (Widelands::MapObjectType::WAREHOUSE):
- case (Widelands::MapObjectType::PRODUCTIONSITE):
- case (Widelands::MapObjectType::MILITARYSITE):
- case (Widelands::MapObjectType::TRAININGSITE): {
- const Widelands::BuildingDescr* descr =
- tribe.get_building_descr(lists_.at(key)->get_selected());
- descname = descr->descname();
- cr->push_arg(descr);
- break;
- }
- case (Widelands::MapObjectType::WARE): {
- const Widelands::WareDescr* descr = tribe.get_ware_descr(lists_.at(key)->get_selected());
- descname = descr->descname();
- cr->push_arg(descr);
- break;
- }
- case (Widelands::MapObjectType::WORKER):
- case (Widelands::MapObjectType::CARRIER):
- case (Widelands::MapObjectType::SOLDIER): {
- const Widelands::WorkerDescr* descr =
- tribe.get_worker_descr(lists_.at(key)->get_selected());
- descname = descr->descname();
- cr->push_arg(descr);
- break;
- }
- case (Widelands::MapObjectType::MAPOBJECT):
- case (Widelands::MapObjectType::BATTLE):
- case (Widelands::MapObjectType::FLEET):
- case (Widelands::MapObjectType::BOB):
- case (Widelands::MapObjectType::CRITTER):
- case (Widelands::MapObjectType::SHIP):
- case (Widelands::MapObjectType::IMMOVABLE):
- case (Widelands::MapObjectType::FLAG):
- case (Widelands::MapObjectType::ROAD):
- case (Widelands::MapObjectType::PORTDOCK):
- throw wexception("EncyclopediaWindow: No MapObjectType defined for tab.");
- }
-
- cr->resume();
- const std::string help_text = cr->pop_string();
- contents_.at(key)->set_text((boost::format("%s%s") % heading(descname) % help_text).str());
+ std::unique_ptr<LuaTable> table(lua_->run_script(entry.script_path));
+ if (!entry.script_parameters.empty()) {
+ std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func"));
+ for (const std::string& parameter : entry.script_parameters) {
+ cr->push_arg(parameter);
+ }
+ cr->resume();
+ table = cr->pop_table();
+ }
+ contents_.at(tab_name)->set_text((boost::format("%s%s")
+ % heading(table->get_string("title"))
+ % table->get_string("text")).str());
} catch (LuaError& err) {
- contents_.at(key)->set_text(err.what());
+ contents_.at(tab_name)->set_text(err.what());
}
- contents_.at(key)->scroll_to_top();
+ contents_.at(tab_name)->scroll_to_top();
}
+
+} // namespace UI
=== renamed file 'src/wui/encyclopedia_window.h' => 'src/ui_basic/encyclopedia_window.h'
--- src/wui/encyclopedia_window.h 2016-02-14 14:09:29 +0000
+++ src/ui_basic/encyclopedia_window.h 2016-03-22 12:21:57 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2004, 2006, 2009 by the Widelands Development Team
+ * Copyright (C) 2002-2016 by the Widelands Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,57 +17,46 @@
*
*/
-#ifndef WL_WUI_ENCYCLOPEDIA_WINDOW_H
-#define WL_WUI_ENCYCLOPEDIA_WINDOW_H
+#ifndef WL_UI_BASIC_ENCYCLOPEDIA_WINDOW_H
+#define WL_UI_BASIC_ENCYCLOPEDIA_WINDOW_H
#include <map>
#include <memory>
+#include <vector>
-#include "logic/map_objects/map_object.h"
-#include "logic/map_objects/tribes/tribe_descr.h"
+#include "scripting/lua_interface.h"
+#include "scripting/lua_table.h"
#include "ui_basic/box.h"
#include "ui_basic/listselect.h"
#include "ui_basic/multilinetextarea.h"
#include "ui_basic/table.h"
#include "ui_basic/tabpanel.h"
#include "ui_basic/unique_window.h"
-#include "ui_basic/window.h"
-
-class InteractivePlayer;
+
+class InteractiveBase;
+
+namespace UI {
struct EncyclopediaWindow : public UI::UniqueWindow {
- EncyclopediaWindow(InteractivePlayer&, UI::UniqueWindow::Registry&);
+ EncyclopediaWindow(InteractiveBase&, UI::UniqueWindow::Registry&, LuaInterface* const lua);
+
+protected:
+ void init(InteractiveBase& parent, std::unique_ptr<LuaTable> table);
+
+ LuaInterface* const lua_;
private:
struct EncyclopediaEntry {
- EncyclopediaEntry(const EncyclopediaEntry&) = default;
- EncyclopediaEntry& operator = (const EncyclopediaEntry&) = default;
- EncyclopediaEntry(const Widelands::DescriptionIndex i,
- const std::string& init_descname,
- const Image* init_icon)
- : index(i), descname(init_descname), icon(init_icon) {
- }
- Widelands::DescriptionIndex index;
- std::string descname;
- const Image* icon;
-
- bool operator<(const EncyclopediaEntry other) const {
- return descname < other.descname;
- }
+ EncyclopediaEntry(const std::string& init_script_path,
+ const std::vector<std::string>& init_script_parameters)
+ : script_path(init_script_path), script_parameters(init_script_parameters) {
+ }
+ const std::string script_path;
+ const std::vector<std::string> script_parameters;
};
- InteractivePlayer& iaplayer() const;
-
- // Fill table of contents
- void fill_entries(const char* key, std::vector<EncyclopediaEntry>* entries);
- void fill_buildings();
- void fill_wares();
- void fill_workers();
-
// Update contents when an entry is selected
- void entry_selected(const std::string& key,
- const std::string& script_path,
- const Widelands::MapObjectType& type);
+ void entry_selected(const std::string& tab_name);
// UI elements
UI::TabPanel tabs_;
@@ -77,9 +66,11 @@
// Main contents boxes for each tab
std::map<std::string, std::unique_ptr<UI::Box>> boxes_;
// A tab's table of contents
- std::map<std::string, std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>> lists_;
+ std::map<std::string, std::unique_ptr<UI::Listselect<EncyclopediaEntry>>> lists_;
// The contents shown when an entry is selected in a tab
std::map<std::string, std::unique_ptr<UI::MultilineTextarea>> contents_;
};
-#endif // end of include guard: WL_WUI_ENCYCLOPEDIA_WINDOW_H
+} // namespace UI
+
+#endif // end of include guard: WL_UI_BASIC_ENCYCLOPEDIA_WINDOW_H
=== modified file 'src/wui/CMakeLists.txt'
--- src/wui/CMakeLists.txt 2016-02-06 18:58:57 +0000
+++ src/wui/CMakeLists.txt 2016-03-22 12:21:57 +0000
@@ -93,8 +93,6 @@
debugconsole.cc
debugconsole.h
dismantlesitewindow.cc
- encyclopedia_window.cc
- encyclopedia_window.h
fieldaction.cc
fieldaction.h
game_debug_ui.cc
@@ -161,6 +159,8 @@
trainingsitewindow.cc
transport_draw.cc
transport_ui.cc
+ tribal_encyclopedia.cc
+ tribal_encyclopedia.h
unique_window_handler.cc
unique_window_handler.h
ware_statistics_menu.cc
@@ -204,7 +204,6 @@
scripting_lua_table
sound
ui_basic
- ui_fsmenu
widelands_ball_of_mud
wui_chat_ui
wui_edge_overlay_manager
=== modified file 'src/wui/game_options_menu.cc'
--- src/wui/game_options_menu.cc 2016-01-29 08:37:22 +0000
+++ src/wui/game_options_menu.cc 2016-03-22 12:21:57 +0000
@@ -27,7 +27,6 @@
#include "base/i18n.h"
#include "graphic/graphic.h"
#include "sound/sound_handler.h"
-#include "ui_fsmenu/fileview.h"
#include "wui/game_main_menu_save_game.h"
#include "wui/game_options_sound_menu.h"
#include "wui/unique_window_handler.h"
@@ -71,27 +70,6 @@
windows_(windows),
box_(this, margin, margin, UI::Box::Vertical,
width, get_h() - 2 * margin, vspacing),
- readme_
- (&box_, "readme",
- 0, 0, width, 0,
- g_gr->images().get("images/ui_basic/but4.png"),
- _("README"),
- /** TRANSLATORS: Button tooltip */
- _("Show general information about Widelands and keyboard shortcuts")),
- license_
- (&box_, "license",
- 0, 0, width, 0,
- g_gr->images().get("images/ui_basic/but4.png"),
- _("License"),
- /** TRANSLATORS: Button tooltip */
- _("Show the distribution licence document")),
- authors_
- (&box_, "authors",
- 0, 0, width, 0,
- g_gr->images().get("images/ui_basic/but4.png"),
- _("Authors"),
- /** TRANSLATORS: Button tooltip */
- _("Show information about the Widelands Development Team")),
sound_
(&box_, "sound_options",
0, 0, width, 0,
@@ -114,49 +92,22 @@
/** TRANSLATORS: Button tooltip */
_("Exit Game"))
{
- box_.add(&readme_, UI::Align::kHCenter);
- box_.add(&license_, UI::Align::kHCenter);
- box_.add(&authors_, UI::Align::kHCenter);
- box_.add_space(vgap);
box_.add(&sound_, UI::Align::kHCenter);
box_.add_space(vgap);
box_.add(&save_game_, UI::Align::kHCenter);
box_.add(&exit_game_, UI::Align::kHCenter);
- box_.set_size(width, 4 * readme_.get_h() + 2 * save_game_.get_h() + 2 * vgap + 7 * vspacing);
+ box_.set_size(width, sound_.get_h() + 2 * save_game_.get_h() + vgap + 3 * vspacing);
set_inner_size(get_inner_w(), box_.get_h() + 2 * margin);
- readme_.sigclicked.connect
- (boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.readme)));
- license_.sigclicked.connect
- (boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.license)));
- authors_.sigclicked.connect
- (boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.authors)));
sound_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_sound, boost::ref(*this)));
save_game_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_save_game, boost::ref(*this)));
exit_game_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_exit_game, boost::ref(*this)));
-
- windows_.readme.open_window = boost::bind
- (&fileview_window, boost::ref(igb_),
- boost::ref(windows_.readme),
- "txts/README.lua");
- windows_.license.open_window = boost::bind
- (&fileview_window, boost::ref(igb_),
- boost::ref(windows_.license),
- "txts/LICENSE.lua");
- windows_.authors.open_window = boost::bind
- (&fileview_window, boost::ref(igb_),
- boost::ref(windows_.license),
- "txts/AUTHORS.lua");
-
#define INIT_BTN_HOOKS(registry, btn) \
registry.on_create = std::bind(&UI::Button::set_perm_pressed, &btn, true); \
registry.on_delete = std::bind(&UI::Button::set_perm_pressed, &btn, false); \
if (registry.window) btn.set_perm_pressed(true); \
- INIT_BTN_HOOKS(windows_.readme, readme_)
- INIT_BTN_HOOKS(windows_.license, license_)
- INIT_BTN_HOOKS(windows_.authors, authors_)
INIT_BTN_HOOKS(windows_.sound_options, sound_)
if (get_usedefaultpos())
=== modified file 'src/wui/game_options_menu.h'
--- src/wui/game_options_menu.h 2015-09-25 13:08:22 +0000
+++ src/wui/game_options_menu.h 2016-03-22 12:21:57 +0000
@@ -39,9 +39,6 @@
InteractiveGameBase& igb_;
InteractiveGameBase::GameMainMenuWindows& windows_;
UI::Box box_;
- UI::Button readme_;
- UI::Button license_;
- UI::Button authors_;
UI::Button sound_;
UI::Button save_game_;
UI::Button exit_game_;
=== modified file 'src/wui/helpwindow.cc'
--- src/wui/helpwindow.cc 2016-02-03 22:42:34 +0000
+++ src/wui/helpwindow.cc 2016-03-22 12:21:57 +0000
@@ -44,16 +44,18 @@
(boost::format(_("Help: %s")) % building_description.descname()).str()),
textarea_(new MultilineTextarea(this, 5, 5, width - 10, height - 10, std::string(), UI::Align::kLeft))
{
- assert(tribe.has_building(tribe.building_index(building_description.name())));
+ assert(tribe.has_building(tribe.building_index(building_description.name())) ||
+ building_description.type() == Widelands::MapObjectType::MILITARYSITE);
try {
std::unique_ptr<LuaTable> t(
lua->run_script("tribes/scripting/help/building_help.lua"));
std::unique_ptr<LuaCoroutine> cr(t->get_coroutine("func"));
cr->push_arg(tribe.name());
- cr->push_arg(&building_description);
+ cr->push_arg(building_description.name());
cr->resume();
- const std::string help_text = cr->pop_string();
- textarea_->set_text(help_text);
+ std::unique_ptr<LuaTable> return_table = cr->pop_table();
+ return_table->do_not_warn_about_unaccessed_keys();
+ textarea_->set_text(return_table->get_string("text"));
} catch (LuaError& err) {
textarea_->set_text(err.what());
}
=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc 2016-02-09 16:29:48 +0000
+++ src/wui/interactive_player.cc 2016-03-22 12:21:57 +0000
@@ -44,7 +44,7 @@
#include "ui_basic/unique_window.h"
#include "wui/building_statistics_menu.h"
#include "wui/debugconsole.h"
-#include "wui/encyclopedia_window.h"
+#include "wui/tribal_encyclopedia.h"
#include "wui/fieldaction.h"
#include "wui/game_chat_menu.h"
#include "wui/game_main_menu.h"
@@ -156,7 +156,7 @@
INIT_BTN_HOOKS(encyclopedia_, toggle_help_)
INIT_BTN_HOOKS(message_menu_, toggle_message_menu_)
- encyclopedia_.open_window = [this] {new EncyclopediaWindow(*this, encyclopedia_);};
+ encyclopedia_.open_window = [this] {new TribalEncyclopedia(*this, encyclopedia_, &game().lua());};
options_.open_window = [this] {new GameOptionsMenu(*this, options_, main_windows_);};
statisticsmenu_.open_window = [this] {
new GameMainMenu(*this, statisticsmenu_, main_windows_);
=== added file 'src/wui/tribal_encyclopedia.cc'
--- src/wui/tribal_encyclopedia.cc 1970-01-01 00:00:00 +0000
+++ src/wui/tribal_encyclopedia.cc 2016-03-22 12:21:57 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "wui/tribal_encyclopedia.h"
+
+#include <memory>
+
+#include <boost/format.hpp>
+
+#include "base/i18n.h"
+#include "logic/map_objects/tribes/tribe_descr.h"
+#include "logic/player.h"
+#include "scripting/lua_coroutine.h"
+#include "scripting/lua_interface.h"
+#include "scripting/lua_table.h"
+#include "ui_basic/messagebox.h"
+#include "wui/interactive_player.h"
+
+TribalEncyclopedia::TribalEncyclopedia(InteractivePlayer& parent, UI::UniqueWindow::Registry& registry, LuaInterface* const lua)
+ : EncyclopediaWindow(parent, registry, lua)
+{
+ const Widelands::TribeDescr& tribe = parent.player().tribe();
+ try {
+ std::unique_ptr<LuaTable> table(lua_->run_script("tribes/scripting/help/init.lua"));
+ std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func"));
+ cr->push_arg(tribe.name());
+ cr->resume();
+ init(parent, cr->pop_table());
+ } catch (LuaError& err) {
+ log("Error loading script for tribal encyclopedia:\n%s\n", err.what());
+ UI::WLMessageBox wmb(
+ &parent,
+ _("Error!"),
+ (boost::format("Error loading script for tribal encyclopedia:\n%s") % err.what()).str(),
+ UI::WLMessageBox::MBoxType::kOk);
+ wmb.run<UI::Panel::Returncodes>();
+ }
+}
=== added file 'src/wui/tribal_encyclopedia.h'
--- src/wui/tribal_encyclopedia.h 1970-01-01 00:00:00 +0000
+++ src/wui/tribal_encyclopedia.h 2016-03-22 12:21:57 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WL_WUI_TRIBAL_ENCYCLOPEDIA_H
+#define WL_WUI_TRIBAL_ENCYCLOPEDIA_H
+
+#include "scripting/lua_interface.h"
+#include "ui_basic/encyclopedia_window.h"
+#include "ui_basic/unique_window.h"
+
+class InteractivePlayer;
+
+struct TribalEncyclopedia : public UI::EncyclopediaWindow {
+ TribalEncyclopedia(InteractivePlayer&, UI::UniqueWindow::Registry&, LuaInterface* const lua);
+};
+
+#endif // end of include guard: WL_WUI_TRIBAL_ENCYCLOPEDIA_H
=== modified file 'test/maps/lua_testsuite.wmf/scripting/tribes_descriptions.lua'
--- test/maps/lua_testsuite.wmf/scripting/tribes_descriptions.lua 2015-10-31 12:11:44 +0000
+++ test/maps/lua_testsuite.wmf/scripting/tribes_descriptions.lua 2016-03-22 12:21:57 +0000
@@ -25,18 +25,27 @@
end
function test_descr:test_get_buildings()
- local nobuildings = function(t)
- local count = 0
- for _ in pairs(t) do count = count + 1 end
- return count
- end
-
local tribe = egbase:get_tribe_description("atlanteans")
- assert_equal(41, nobuildings(tribe.buildings))
+ assert_equal(41, #tribe.buildings)
tribe = egbase:get_tribe_description("barbarians")
- assert_equal(50, nobuildings(tribe.buildings))
+ assert_equal(50, #tribe.buildings)
tribe = egbase:get_tribe_description("empire")
- assert_equal(51, nobuildings(tribe.buildings))
+ assert_equal(51, #tribe.buildings)
+
+ -- Test if buildings have been casted to their correct types
+ for i, building in ipairs(tribe.buildings) do
+ if (building.type_name == "productionsite") then
+ assert_true(#building.production_programs > 0)
+ elseif (building.type_name == "militarysite") then
+ assert_true(building.heal_per_second > 0)
+ assert_true(building.max_number_of_soldiers > 0)
+ elseif (building.type_name == "warehouse") then
+ assert_true(building.heal_per_second > 0)
+ assert_true(building.max_number_of_soldiers == nil)
+ elseif (building.type_name == "trainingsite") then
+ assert_true(building.max_attack ~= nil or building.max_defense ~= nil or building.max_evade ~= nil or building.max_health ~= nil)
+ end
+ end
end
function test_descr:test_get_carrier()
@@ -76,34 +85,20 @@
function test_descr:test_get_wares()
local tribe = egbase:get_tribe_description("atlanteans")
- local nowares = function(t)
- local count = 0
- for _ in pairs(t) do count = count + 1 end
- return count
- end
-
- local tribe = egbase:get_tribe_description("atlanteans")
- assert_equal(44, nowares(tribe.wares))
+ assert_equal(44, #tribe.wares)
tribe = egbase:get_tribe_description("barbarians")
- assert_equal(40, nowares(tribe.wares))
+ assert_equal(40, #tribe.wares)
tribe = egbase:get_tribe_description("empire")
- assert_equal(44, nowares(tribe.wares))
+ assert_equal(44, #tribe.wares)
end
function test_descr:test_get_workers()
local tribe = egbase:get_tribe_description("atlanteans")
- local noworkers = function(t)
- local count = 0
- for _ in pairs(t) do count = count + 1 end
- return count
- end
-
- local tribe = egbase:get_tribe_description("atlanteans")
- assert_equal(29, noworkers(tribe.workers))
+ assert_equal(29, #tribe.workers)
tribe = egbase:get_tribe_description("barbarians")
- assert_equal(31, noworkers(tribe.workers))
+ assert_equal(31, #tribe.workers)
tribe = egbase:get_tribe_description("empire")
- assert_equal(32, noworkers(tribe.workers))
+ assert_equal(32, #tribe.workers)
end
function test_descr:test_has_building()
Follow ups
-
[Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: noreply, 2016-04-02
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-04-02
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-04-02
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-04-02
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-04-02
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-04-01
-
[Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: bunnybot, 2016-04-01
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-04-01
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: Miroslav Remák, 2016-03-31
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-03-28
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-03-28
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-28
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-03-28
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-26
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-25
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-25
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-25
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-03-25
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: TiborB, 2016-03-24
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-24
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: kaputtnik, 2016-03-23
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: GunChleoc, 2016-03-23
-
Re: [Merge] lp:~widelands-dev/widelands/lua-driven-help into lp:widelands
From: TiborB, 2016-03-23