void scrollbar_widget::set_value(const std::string& key, const variant& v) { if(key == "on_scroll") { ffl_handler_ = get_environment()->create_formula(v["on_scroll"]); } else if(key == "up_arrow") { up_arrow_ = widget_factory::create(v, get_environment()); } else if(key == "down_arrow") { down_arrow_ = widget_factory::create(v, get_environment()); } else if(key == "handle") { handle_ = widget_factory::create(v, get_environment()); } else if(key == "handle_bottom") { handle_bot_ = widget_factory::create(v, get_environment()); } else if(key == "handle_top") { handle_top_ = widget_factory::create(v, get_environment()); } else if(key == "background") { background_ = widget_factory::create(v, get_environment()); } else if(key == "range") { std::vector<int> range = v.as_list_int(); ASSERT_EQ(range.size(), 2); set_range(range[0], range[1]); } else if(key == "position") { window_pos_ = v.as_int(); clip_window_position(); } widget::set_value(key, v); }
void variant::swap(variant& other) { if (this == &other) return; const bool is_this_valid = is_valid(); const bool is_other_valid = other.is_valid(); if (!is_this_valid && !is_other_valid) return; if (is_this_valid && is_other_valid) { detail::variant_data tmp_data; detail::variant_policy_func tmp_policy_func = other.m_policy; other.m_policy(detail::variant_policy_operation::SWAP, other.m_data, tmp_data); m_policy(detail::variant_policy_operation::SWAP, m_data, other.m_data); other.m_policy = m_policy; tmp_policy_func(detail::variant_policy_operation::SWAP, tmp_data, m_data); m_policy = tmp_policy_func; } else { detail::variant_data& full_data = is_this_valid ? m_data : other.m_data; detail::variant_data& empty_data = is_this_valid ? other.m_data : m_data; detail::variant_policy_func full_policy_func = is_this_valid ? m_policy : other.m_policy; full_policy_func(detail::variant_policy_operation::SWAP, full_data, empty_data); std::swap(m_policy, other.m_policy); } }
void dropdown_widget::set_value(const std::string& key, const variant& v) { if(key == "on_change") { on_change_ = boost::bind(&dropdown_widget::change_delegate, this, _1); change_handler_ = get_environment()->create_formula(v); } else if(key == "on_select") { on_select_ = boost::bind(&dropdown_widget::select_delegate, this, _1, _2); select_handler_ = get_environment()->create_formula(v); } else if(key == "item_list") { list_ = v.as_list_string(); current_selection_ = 0; } else if(key == "selection") { current_selection_ = v.as_int(); } else if(key == "type") { std::string s = v.as_string(); if(s == "combo" || s == "combobox") { type_ = DROPDOWN_COMBOBOX; } else if(s == "list" || s == "listbox") { type_ = DROPDOWN_LIST; } else { ASSERT_LOG(false, "Unreognised type: " << s); } } widget::set_value(key, v); }
variant variant::operator/(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { int denominator = v.as_decimal(); if(denominator == 0) { throw type_error((formatter() << "divide by zero error").str()); } long long long_int = as_decimal(); long_int *= 10000; long_int /= denominator; if( long_int%10 >= 5) { long_int /= 10; ++long_int; } else long_int/=10; return variant( static_cast<int>(long_int) , variant::DECIMAL_VARIANT); } const int numerator = as_int(); const int denominator = v.as_int(); if(denominator == 0) { throw type_error((formatter() << "divide by zero error").str());; } return variant(numerator/denominator); }
int from_variant(variant node) { if(node.is_string()) { return from_string(node.as_string()); } return node.as_int(-1); }
void BlendMode::set(const variant& node) { if(node.is_string()) { const std::string& blend = node.as_string(); if(blend == "add") { set(BlendModeConstants::BM_ONE, BlendModeConstants::BM_ONE); } else if(blend == "alpha_blend") { set(BlendModeConstants::BM_SRC_ALPHA, BlendModeConstants::BM_ONE_MINUS_SRC_ALPHA); } else if(blend == "colour_blend" || blend == "color_blend") { set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ONE_MINUS_SRC_COLOR); } else if(blend == "modulate") { set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_ZERO); } else if(blend == "src_colour one" || blend == "src_color one") { set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ONE); } else if(blend == "src_colour zero" || blend == "src_color zero") { set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_ZERO); } else if(blend == "src_colour dest_colour" || blend == "src_color dest_color") { set(BlendModeConstants::BM_SRC_COLOR, BlendModeConstants::BM_DST_COLOR); } else if(blend == "dest_colour one" || blend == "dest_color one") { set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_ONE); } else if(blend == "dest_colour src_colour" || blend == "dest_color src_color") { set(BlendModeConstants::BM_DST_COLOR, BlendModeConstants::BM_SRC_COLOR); } else { ASSERT_LOG(false, "BlendMode: Unrecognised scene_blend mode " << blend); } } else if(node.is_list() && node.num_elements() >= 2) { ASSERT_LOG(node[0].is_string() && node[1].is_string(), "BlendMode: Blend mode must be specified by a list of two strings."); set(parse_blend_string(node[0].as_string()), parse_blend_string(node[1].as_string())); } else { ASSERT_LOG(false, "BlendMode: Setting blend requires either a string or a list of greater than two elements." << node.to_debug_string()); } }
std::string Visitor::visit(variant & object) { create_model_map(); Derived *base = (Derived *)*object; std::string classname; if (!object) { printf("visit was empty!\n"); return ""; } if (ClassMap::is_recognized_classname(object.type().name())) { classname = base->classname(); } else { if (object.isString() || object.isType<bool>()) classname = "quoted"; else if (object.isType<std::vector<variant> >()) classname = "array"; else classname = "literal"; } method_dict_map_t method_dict_map = method_dictionary(); if (method_dict_map[classname]) { return (this->*method_dict_map[classname])(object); } else { printf("Visitor::visit failed to find method: %s(%s)\n", classname.c_str(), object.type().name()); return ""; } }
world::world(const variant& node) : view_distance_(node["view_distance"].as_int(default_view_distance)), seed_(node["seed"].as_int(0)) { ASSERT_LOG(node.has_key("shader"), "Must have 'shader' attribute"); ASSERT_LOG(node["shader"].is_string(), "'shader' attribute must be a string"); shader_ = gles2::shader_program::get_global(node["shader"].as_string())->shader(); if(node.has_key("lighting")) { lighting_.reset(new graphics::lighting(shader_, node["lighting"])); } if(node.has_key("objects")) { for(int n = 0; n != node["objects"].num_elements(); ++n) { add_object(new user_voxel_object(node["objects"][n])); } } if(node.has_key("skybox")) { skybox_.reset(new graphics::skybox(node["skybox"])); } if(node.has_key("chunks")) { logic_.reset(new logical_world(node)); build_fixed(node["chunks"]); } else { build_infinite(); } }
checkbox::checkbox(const variant& v, game_logic::formula_callable* e) : checked_(false), button(v,e) { hpadding_ = v["hpad"].as_int(12); if(v.has_key("padding")) { ASSERT_LOG(v["padding"].num_elements() == 2, "Incorrect number of padding elements specifed." << v["padding"].num_elements()); hpadding_ = v["padding"][0].as_int(); } checked_ = v["checked"].as_bool(false); variant label_var = v["label"]; label_ = (label_var.is_map() || label_var.is_callable()) ? "" : label_var.as_string_default("Checkbox"); label_widget_ = (label_var.is_map() || label_var.is_callable()) ? widget_factory::create(label_var, e) : widget_ptr(new graphical_font_label(label_, "door_label", 2)); ASSERT_LOG(get_environment() != 0, "You must specify a callable environment"); click_handler_ = get_environment()->create_formula(v["on_click"]); onclick_ = boost::bind(&checkbox::click, this, _1); set_click_handler(boost::bind(&checkbox::on_click, this)); set_label(create_checkbox_widget(label_widget_, checked_, button_resolution(), hpadding_)); if(v.has_key("width") || v.has_key("height")) { set_dim(v["width"].as_int(width()), v["height"].as_int(height())); } }
template<> decimal manhattan_distance(const variant& p1, const variant& p2) { const std::vector<decimal>& v1 = p1.as_list_decimal(); const std::vector<decimal>& v2 = p2.as_list_decimal(); decimal x1 = v1[0] - v2[0]; decimal x2 = v1[1] - v2[1]; return (x1 < 0 ? -x1 : x1) + (x2 < 0 ? -x2 : x2); }
Model read_model(const variant& v) { Model model; if(v.has_key("feet")) { model.feet_position = read_voxel_pos(v["feet"]); } else { model.feet_position[0] = model.feet_position[1] = model.feet_position[2] = 0; } if(v.has_key("scale")) { model.scale = v["scale"].as_decimal(); } else { model.scale = decimal::from_int(1); } for(const std::pair<variant,variant>& p : v["layers"].as_map()) { LayerType layer_type = read_layer_type(p.second); layer_type.name = p.first.as_string(); model.layer_types.push_back(layer_type); } for(const std::pair<variant,variant>& p : v["animations"].as_map()) { Animation anim = read_animation(p.second); anim.name = p.first.as_string(); model.animations.push_back(anim); } if(v.has_key("attachment_points")) { model.attachment_points = read_attachment_points(v["attachment_points"]); } return model; }
variant variant::operator*(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant(as_decimal() * v.as_decimal()); } if(type_ == TYPE_LIST) { int ncopies = v.as_int(); if(ncopies < 0) { ncopies *= -1; } const std::vector<variant>& items = list_->elements; std::vector<variant> res; res.reserve(items.size()*ncopies); for(int n = 0; n != ncopies; ++n) { for(int m = 0; m != items.size(); ++m) { res.push_back(items[m]); } } return variant(&res); } return variant(as_int() * v.as_int()); }
bool variant::operator==(const variant& v) const { if(type_ != v.type_) { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return as_decimal() == v.as_decimal(); } return false; } switch(type_) { case TYPE_NULL: { return v.is_null(); } case TYPE_STRING: { return string_->str == v.string_->str; } case TYPE_INT: { return int_value_ == v.int_value_; } case TYPE_DECIMAL: { return decimal_value_ == v.decimal_value_; } case TYPE_LIST: { if(num_elements() != v.num_elements()) { return false; } for(size_t n = 0; n != num_elements(); ++n) { if((*this)[n] != v[n]) { return false; } } return true; } case TYPE_MAP: { return map_->elements == v.map_->elements; } case TYPE_CALLABLE_LOADING: { return false; } case TYPE_CALLABLE: { return callable_->equals(v.callable_); } case TYPE_FUNCTION: { return fn_ == v.fn_; } } assert(false); return false; }
std::string formula_ai::evaluate(const std::string& formula_str) { try{ game_logic::formula f(formula_str, &function_table_); game_logic::map_formula_callable callable(this); callable.add_ref(); //formula_debugger fdb; const variant v = f.evaluate(callable,NULL); if (ai_ptr_) { variant var = execute_variant(v, *ai_ptr_, true ); if ( !var.is_empty() ) { return "Made move: " + var.to_debug_string(); } } return v.to_debug_string(); } catch(formula_error& e) { e.line = 0; handle_exception(e); throw; } }
std::vector<CastlePart> parse_dir(const variant& node) { std::vector<CastlePart> res; const std::vector<std::string> keys = { "bl", "br", "l", "r", "tl", "tr" }; ASSERT_LOG(node.is_map(), "must be a map type."); for(auto key : keys) { ASSERT_LOG(node.has_key(key), "Must have attribute '" << key << "' in definition."); const variant& dir = node[key]; ASSERT_LOG(dir.has_key("rect"), "Attribute '" << key << "' must have 'rect' definition."); CastlePart cp; cp.r_ = rect(dir["rect"]); if(dir.has_key("border")) { ASSERT_LOG(dir["border"].num_elements() == 4, "'border' attribute must be list of 4 integers."); for(int n = 0; n != 4; ++n) { cp.border_[n] = dir["border"][n].as_int32(); } } else { for(int n = 0; n != 4; ++n) { cp.border_[n] = 0; } } if(dir.has_key("offset")) { cp.offs_ = point(dir["offset"]); } else { cp.offs_.x = cp.offs_.y = 0; } res.emplace_back(cp); } return res; }
variant variant::operator-(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant( as_decimal() - v.as_decimal() , DECIMAL_VARIANT); } return variant(as_int() - v.as_int()); }
void load_castle_definitions(const variant& castle_def) { ASSERT_LOG(castle_def.is_map(), "Castle definitions must be a map."); for(const auto& def : castle_def.as_map()) { const std::string name = def.first.as_string(); get_castle_def()[name] = std::make_shared<CastleDef>(name, def.second); } }
VoxelPos read_voxel_pos(const variant& v) { std::vector<int> res = v.as_list_int(); ASSERT_LOG(res.size() == 3, "Illegal voxel pos: " << v.write_json() << " " << v.debug_location()); VoxelPos result; result[0] = res[0]; result[1] = res[1]; result[2] = res[2]; return result; }
void formula_variable_storage::read(variant node) { if(node.is_null()) { return; } foreach(const variant_pair& val, node.as_map()) { add(val.first.as_string(), val.second); } }
oWalletContactEntry WalletDb::lookup_contact( const variant& data )const { try { FC_ASSERT( is_open() ,"Wallet not open!"); FC_ASSERT( !data.is_null() ); const auto iter = contacts.find( data.as_string() ); if( iter != contacts.end() ) return iter->second; return oWalletContactEntry(); } FC_CAPTURE_AND_RETHROW( (data) ) }
owallet_contact_record wallet_db::lookup_contact( const variant& data )const { try { FC_ASSERT( is_open() ); FC_ASSERT( !data.is_null() ); const auto iter = contacts.find( data.as_string() ); if( iter != contacts.end() ) return iter->second; return owallet_contact_record(); } FC_CAPTURE_AND_RETHROW( (data) ) }
frame::frame(variant node) : id_(node["id"].as_string()), image_(node["image"].as_string()), variant_id_(id_), enter_event_id_(get_object_event_id("enter_" + id_ + "_anim")), end_event_id_(get_object_event_id("end_" + id_ + "_anim")), leave_event_id_(get_object_event_id("leave_" + id_ + "_anim")), process_event_id_(get_object_event_id("process_" + id_)), texture_(node.has_key("fbo") ? node["fbo"].convert_to<texture_object>()->texture() : graphics::texture::get(image_, node["image_formula"].as_string_default())), solid_(solid_info::create(node)), collide_rect_(node.has_key("collide") ? rect(node["collide"]) : rect(node["collide_x"].as_int(), node["collide_y"].as_int(), node["collide_w"].as_int(), node["collide_h"].as_int())), hit_rect_(node.has_key("hit") ? rect(node["hit"]) : rect(node["hit_x"].as_int(), node["hit_y"].as_int(), node["hit_w"].as_int(), node["hit_h"].as_int())), platform_rect_(node.has_key("platform") ? rect(node["platform"]) : rect(node["platform_x"].as_int(), node["platform_y"].as_int(), node["platform_w"].as_int(), 1)), img_rect_(node.has_key("rect") ? rect(node["rect"]) : rect(node["x"].as_int(), node["y"].as_int(), node["w"].as_int(), node["h"].as_int())), feet_x_(node["feet_x"].as_int()), feet_y_(node["feet_y"].as_int()), accel_x_(node["accel_x"].as_int(INT_MIN)), accel_y_(node["accel_y"].as_int(INT_MIN)), velocity_x_(node["velocity_x"].as_int(INT_MIN)), velocity_y_(node["velocity_y"].as_int(INT_MIN)), nframes_(node["frames"].as_int(1)), nframes_per_row_(node["frames_per_row"].as_int(-1)), frame_time_(node["duration"].as_int(-1)), reverse_frame_(node["reverse"].as_bool()), play_backwards_(node["play_backwards"].as_bool()), scale_(node["scale"].as_int(2)), pad_(node["pad"].as_int()), rotate_(node["rotate"].as_int()), blur_(node["blur"].as_int()), rotate_on_slope_(node["rotate_on_slope"].as_bool()), damage_(node["damage"].as_int()), sounds_(util::split(node["sound"].as_string_default())), no_remove_alpha_borders_(node["no_remove_alpha_borders"].as_bool(false)), collision_areas_inside_frame_(true), current_palette_(-1) { std::vector<std::string> hit_frames = util::split(node["hit_frames"].as_string_default()); foreach(const std::string& f, hit_frames) { hit_frames_.push_back(boost::lexical_cast<int>(f)); }
bool variant::operator<=(const variant& v) const { if(type_ != v.type_) { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return as_decimal() <= v.as_decimal(); } return type_ < v.type_; } switch(type_) { case TYPE_NULL: { return true; } case TYPE_STRING: { return string_->str <= v.string_->str; } case TYPE_INT: { return int_value_ <= v.int_value_; } case TYPE_DECIMAL: { return decimal_value_ <= v.decimal_value_; } case TYPE_LIST: { for(size_t n = 0; n != num_elements() && n != v.num_elements(); ++n) { if((*this)[n] < v[n]) { return true; } else if((*this)[n] > v[n]) { return false; } } return num_elements() <= v.num_elements(); } case TYPE_MAP: { return map_->elements <= v.map_->elements; } case TYPE_CALLABLE_LOADING: { return false; } case TYPE_CALLABLE: { return !v.callable_->less(callable_); } } assert(false); return false; }
RenderTarget::RenderTarget(const variant& node) : width_(0), height_(0), color_attachments_(1), depth_attachment_(false), stencil_attachment_(false), multi_sampling_(false), multi_samples_(0), clear_color_(0.0f, 0.0f, 0.0f, 1.0f) { ASSERT_LOG(node.is_map(), "RenderTarget definitions must be maps: " << node.to_debug_string()); ASSERT_LOG(node.has_key("width"), "Render target must have a 'width' attribute."); ASSERT_LOG(node.has_key("height"), "Render target must have a 'height' attribute."); width_ = node["width"].as_int32(); height_ = node["height"].as_int32(); if(node.has_key("color_planes")) { color_attachments_ = node["color_planes"].as_int32(); ASSERT_LOG(color_attachments_ >= 0, "Number of 'color_planes' must be zero or greater: " << color_attachments_); } if(node.has_key("depth_buffer")) { depth_attachment_ = node["depth_buffer"].as_bool(); } if(node.has_key("stencil_buffer")) { stencil_attachment_ = node["stencil_buffer"].as_bool(); } if(node.has_key("use_multisampling")) { multi_sampling_ = node["use_multisampling"].as_bool(); if(node.has_key("samples")) { multi_samples_ = node["samples"].as_int32(); } } // XXX Maybe we need to add some extra filtering from min to max values based on order ? }
bool variant_compare_less(const variant& lhs, const type& lhs_type, const variant& rhs, const type& rhs_type) { if (lhs_type.is_arithmetic() && rhs_type.is_arithmetic()) { if (is_floating_point(lhs_type) || is_floating_point(rhs_type)) return (lhs.to_double() < rhs.to_double()); else return (lhs.to_int64() < rhs.to_int64()); } else { variant lhs_tmp; if (lhs.convert(rhs_type, lhs_tmp)) return lhs_tmp.compare_less(rhs); if (!lhs.is_nullptr() && rhs.is_nullptr()) return false; // as last try, do a string conversion bool ok1 = false; bool ok2 = false; auto ret = (lhs.to_string(&ok1) < rhs.to_string(&ok2)); if (ok1 && ok2) return ret; else return (lhs_type < rhs_type); } }
void xml_writer_impl::write_instruction(const variant& instruction) { if (instruction.is<variant::Mapping>() && instruction.has_key(xml_target) && instruction.has_key(xml_data)) { m_os << "<?" << instruction[xml_target].as<std::string>() << " " << instruction[xml_data].as<std::string>() << "?>"; } else { boost::throw_exception(variant_error((boost::format("Expecting dictionary containing '%s' and '%s' for processing instruction") % xml_target % xml_data).str())); } }
void scrollable_widget::set_value(const std::string& key, const variant& v) { if(key == "yscroll") { set_yscroll(v.as_int()); } else if(key == "virtual_height") { set_virtual_height(v.as_int()); } else if(key == "step") { set_scroll_step(v.as_int()); } widget::set_value(key, v); }
bool variant_compare_equal(const variant& lhs, const type& lhs_type, const variant& rhs, const type& rhs_type) { if (is_floating_point(lhs_type) || is_floating_point(rhs_type)) { return almost_equal(lhs.to_double(), rhs.to_double()); } else { return (lhs.to_int64() == rhs.to_int64()); } }
grid::grid(const variant& v, game_logic::formula_callable* e) : widget(v, e), scrollable_widget(v, e), row_height_(0), selected_row_(-1), allow_selection_(false), must_select_(false), swallow_clicks_(false), hpad_(0), show_background_(false), max_height_(-1), allow_highlight_(true), set_h_(0), set_w_(0) { ASSERT_LOG(get_environment() != 0, "You must specify a callable environment"); if(v.has_key("on_select")) { ffl_on_select_ = get_environment()->create_formula(v["on_select"]); on_select_ = boost::bind(&grid::select_delegate, this, _1); } if(v.has_key("on_mouseover")) { ffl_on_mouseover_ = get_environment()->create_formula(v["on_mouseover"]); on_select_ = boost::bind(&grid::mouseover_delegate, this, _1); } ncols_ = v["columns"].as_int(1); if(v.has_key("column_widths")) { if(v["column_widths"].is_list()) { std::vector<int> li = v["column_widths"].as_list_int(); col_widths_.assign(li.begin(), li.end()); } else if(v["column_widths"].is_int()) { col_widths_.assign(ncols_, v["column_widths"].as_int()); } else { ASSERT_LOG(false, "grid: column_widths must be an int or list of ints"); } } else { col_widths_.assign(ncols_, 0); } if(v.has_key("column_alignments")) { if(v["column_alignments"].is_list()) { // XXX this could be a list of strings as well. int col = 0; foreach(const variant& c, v["column_alignments"].as_list()) { if(c.is_int()) { set_align(col, static_cast<COLUMN_ALIGN>(c.as_int())); } else if(c.is_string()) { const std::string& s = c.as_string(); if(s == "center" || s == "centre") { set_align(col, ALIGN_CENTER); } else if(s == "right") { set_align(col, ALIGN_RIGHT); } else if(s == "left") { set_align(col, ALIGN_LEFT); } else { ASSERT_LOG(false, "grid: column_alignments must be \"left\", \"right\" or \"center\""); } } else { ASSERT_LOG(false, "grid: column alignment members must be an integer or a string."); } col++; } } else if(v["column_alignments"].is_int()) {
// Given two variants, which are maps merge the properties from v2 into v1 that // don't already exist in v1. void variant_map_merge(variant& v1, const variant& v2) { std::map<variant, variant>::const_iterator v2it = v2.as_map().begin(); std::map<variant, variant>::const_iterator v2end = v2.as_map().end(); while(v2it != v2end) { std::map<variant, variant>::const_iterator v1it = v1.as_map().find(v2it->first); if(v1it == v1.as_map().end()) { v1.add_attr(v2it->first, v2it->second); } v2it++; } }