add the capacity to have variables automatically set in WML

* all SUF now can access the filtered unit via 

* events can access  and  the same way
This commit is contained in:
Jérémy Rosen 2006-12-15 20:56:45 +00:00
parent 8ab001268e
commit 3d86ca3575
6 changed files with 150 additions and 18 deletions

View file

@ -27,7 +27,7 @@
#define ERR_CF LOG_STREAM(err, config)
config::config(const config& cfg)
config::config(const config& cfg):variable_set()
{
append(cfg);
}
@ -649,6 +649,60 @@ void config::debug() const{
i--;
}
const t_string& config::get_variable_const(const std::string& key)
{
const std::string::const_iterator itor = std::find(key.begin(),key.end(),'.');
size_t MaxLoop= 1024;
if(itor != key.end()) {
std::string element(key.begin(),itor);
std::string sub_key(itor+1,key.end());
size_t index = 0;
const std::string::iterator index_start = std::find(element.begin(),element.end(),'[');
const bool explicit_index = index_start != element.end();
if(explicit_index) {
const std::string::iterator index_end = std::find(index_start,element.end(),']');
const std::string index_str(index_start+1,index_end);
index = size_t(atoi(index_str.c_str()));
if(index > MaxLoop) {
index = MaxLoop;
}
element = std::string(element.begin(),index_start);
}
const config::child_list& items = get_children(element);
//special case -- '.length' on an array returns the size of the array
if(explicit_index == false && sub_key == "length") {
static t_string zero_str = "0";
if(items.empty()) {
return zero_str;
} else {
int size = minimum<int>(MaxLoop,int(items.size()));
(*items.back())["__length"] = lexical_cast<std::string>(size);
return (*items.back())["__length"];
}
}
while(get_children(element).size() <= index) {
add_child(element);
}
return (*get_children(element)[index]).get_variable_const(sub_key);
} else {
if(values.find(key) != values.end()){
return values.find(key)->second;
}else {
static t_string empty = "";
return empty;
}
}
}
std::string config::hash() const
{
static const unsigned int hash_length = 128;

View file

@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include "tstring.hpp"
#include "serialization/string_utils.hpp"
//This module defines the interface to Wesnoth Markup Language (WML).
//WML is a simple hierarchical text-based file format. The format
@ -32,7 +33,7 @@ typedef std::map<std::string,t_string> string_map;
//a config object defines a single node in a WML file, with access to
//child nodes.
class config
class config: public variable_set
{
public:
//create an empty node.
@ -141,6 +142,9 @@ public:
//resets the translated values of all strings contained in this object
void reset_translation() const;
// allow any WML to be used to interpolate variables
const t_string& get_variable_const(const std::string& id) ;
//all the attributes of this node.
string_map values;

View file

@ -278,6 +278,9 @@ public:
bool& rebuild_screen() {return rebuild_screen_;}
void add_event_var(const unit* primary_unit, const unit* secondary_unit=NULL);
void rem_event_var();
private:
bool handle_event_command(const queued_event& event_info, const std::string& cmd, const vconfig cfg, bool& mutated);
@ -288,6 +291,26 @@ private:
vconfig cfg_;
};
void event_handler::add_event_var(const unit* primary_unit, const unit* secondary_unit)
{
if(primary_unit) {
config tmp_cfg;
primary_unit->write(tmp_cfg);
cfg_.add_local_var("_primary_unit",tmp_cfg);
}
if(secondary_unit) {
config tmp_cfg;
secondary_unit->write(tmp_cfg);
cfg_.add_local_var("_secondary_unit",tmp_cfg);
}
}
void event_handler::rem_event_var()
{
cfg_.rem_local_var("_primary_unit");
cfg_.rem_local_var("_secondary_unit");
}
gamemap::location cfg_to_loc(const vconfig cfg,int defaultx = 0, int defaulty = 0)
{
int x = lexical_cast_default(cfg["x"], defaultx) - 1;
@ -2038,13 +2061,24 @@ bool process_event(event_handler& handler, const queued_event& ev)
unit_map::iterator unit1 = units->find(ev.loc1);
unit_map::iterator unit2 = units->find(ev.loc2);
unit* tmp_unit1 = NULL;
unit* tmp_unit2 = NULL;
if(unit1!= units->end()) {
tmp_unit1 = &(unit1->second);
}
if(unit2!= units->end()) {
tmp_unit2 = &(unit2->second);
}
handler.add_event_var(tmp_unit1,tmp_unit2);
const vconfig::child_list first_filters = handler.first_arg_filters();
vconfig::child_list::const_iterator ffi;
for(ffi = first_filters.begin();
ffi != first_filters.end(); ++ffi) {
ffi != first_filters.end(); ++ffi) {
if(unit1 == units->end() || !game_events::unit_matches_filter(unit1,*ffi)) {
handler.rem_event_var();
return false;
}
}
@ -2052,33 +2086,36 @@ bool process_event(event_handler& handler, const queued_event& ev)
const vconfig::child_list first_special_filters = handler.first_special_filters();
special_matches = first_special_filters.size() ? false : true;
for(ffi = first_special_filters.begin();
ffi != first_special_filters.end(); ++ffi) {
ffi != first_special_filters.end(); ++ffi) {
if(unit1 != units->end() && game_events::matches_special_filter(ev.data.child("first"),*ffi)) {
special_matches = true;
}
}
if(!special_matches) {
handler.rem_event_var();
return false;
}
const vconfig::child_list second_filters = handler.second_arg_filters();
for(vconfig::child_list::const_iterator sfi = second_filters.begin();
sfi != second_filters.end(); ++sfi) {
sfi != second_filters.end(); ++sfi) {
if(unit2 == units->end() || !game_events::unit_matches_filter(unit2,*sfi)) {
handler.rem_event_var();
return false;
}
}
const vconfig::child_list second_special_filters = handler.second_special_filters();
special_matches = second_special_filters.size() ? false : true;
for(ffi = second_special_filters.begin();
ffi != second_special_filters.end(); ++ffi) {
ffi != second_special_filters.end(); ++ffi) {
if(unit2 != units->end() && game_events::matches_special_filter(ev.data.child("second"),*ffi)) {
special_matches = true;
}
}
if(!special_matches) {
handler.rem_event_var();
return false;
}
@ -2096,6 +2133,7 @@ bool process_event(event_handler& handler, const queued_event& ev)
handler.disable();
}
handler.rem_event_var();
return res;
}

View file

@ -33,6 +33,7 @@
#include "game_events.hpp"
#include "sound.hpp"
#include "sdl_utils.hpp"
#include "variable.hpp"
#include <ctime>
#include <algorithm>
@ -880,8 +881,13 @@ bool unit::has_ability_by_id(const std::string& ability) const
return false;
}
bool unit::matches_filter(const config& cfg,const gamemap::location& loc,bool use_flat_tod) const
bool unit::matches_filter(const config& orig_cfg,const gamemap::location& loc,bool use_flat_tod) const
{
vconfig tmp_vconf(&orig_cfg);
config tmp_unit;
write(tmp_unit);
tmp_vconf.add_local_var("_filtered_unit",tmp_unit);
config cfg = tmp_vconf.get_parsed_config();
const std::string& description = cfg["description"];
const std::string& speaker = cfg["speaker"];
const std::string& type = cfg["type"];

View file

@ -71,8 +71,11 @@ const config vconfig::get_parsed_config() const
for(config::all_children_iterator child = cfg_->ordered_begin();
child != cfg_->ordered_end(); ++child) {
vconfig tmp_vconf= (*child).second;
tmp_vconf.local_vars_ = local_vars_;
res.add_child(*(*child).first, vconfig((*child).second).get_parsed_config());
res.add_child(*(*child).first, tmp_vconf.get_parsed_config());
}
return res;
}
@ -82,35 +85,59 @@ vconfig::child_list vconfig::get_children(const std::string& key) const
const config::child_list& list = cfg_->get_children(key);
vconfig::child_list res(list.size());
std::copy(list.begin(), list.end(),res.begin());
for(vconfig::child_list::iterator itor = res.begin(); itor != res.end() ;itor++) {
itor->local_vars_ = local_vars_;
}
return res;
}
vconfig vconfig::child(const std::string& key) const
{
return vconfig(cfg_->child(key));
vconfig tmp = cfg_->child(key);
tmp.local_vars_ = local_vars_;
return tmp;
}
const t_string& vconfig::operator[](const std::string& key) const
const t_string vconfig::operator[](const std::string& key) const
{
return expand(key);
}
const t_string& vconfig::expand(const std::string& key) const
const t_string vconfig::expand(const std::string& key) const
{
const t_string& val = (*cfg_)[key];
if(repos != NULL && !val.str().empty() && val.str()[0] == '$') {
return repos->get_variable(val.str().substr(1));
if(!val.str().empty() && val.str()[0] == '$') {
std::string tmp = val.str();
// stupid const
config grr = local_vars_;
// first expand local variables
tmp = utils::interpolate_variables_into_string(val.str(),grr);
if(tmp.empty()) tmp = val.str();
// now expand global variables
if(repos != NULL && !tmp.empty() && tmp[0] == '$') {
tmp = repos->get_variable(tmp.substr(1));
if(tmp.empty()) tmp = val.str();
}
return tmp;
} else {
return val;
}
}
const t_string& vconfig::get_attribute(const std::string& key) const
const t_string vconfig::get_attribute(const std::string& key) const
{
return (*cfg_)[key];
}
void vconfig::add_local_var(std::string var_name, config& var)
{
local_vars_.add_child(var_name,var);
}
void vconfig::rem_local_var(std::string var_name)
{
local_vars_.clear_children(var_name);
}
namespace variable
{
manager::manager(game_state* repository)

View file

@ -18,7 +18,7 @@
#include <string>
#include <vector>
class config;
#include "config.hpp"
class t_string;
struct game_state;
@ -43,12 +43,15 @@ public:
child_list get_children(const std::string& key) const;
vconfig child(const std::string& key) const;
const t_string& operator[](const std::string&) const;
const t_string& expand(const std::string&) const; /** < Synonym for operator[] */
const t_string& get_attribute(const std::string&) const;
const t_string operator[](const std::string&) const;
const t_string expand(const std::string&) const; /** < Synonym for operator[] */
const t_string get_attribute(const std::string&) const;
void add_local_var(std::string var_name, config& var);
void rem_local_var(std::string var_name);
private:
const config* cfg_;
config local_vars_;
};
namespace variable