//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) Twan van Laarhoven and the other MSE developers | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ // ----------------------------------------------------------------------------- : Includes #include #include #include #include #include #include #include #include #include #include #include #include // ----------------------------------------------------------------------------- : Helper functions static Value* get_container(GameP& game, CardP& card, String key_name, bool ignore_field_not_found) { // find value container to update IndexMap::const_iterator value_it = card->data.find(key_name); if (value_it == card->data.end()) { // look among alternate names map::iterator alt_name_it = game->card_fields_alt_names.find(unified_form(key_name)); if (alt_name_it != game->card_fields_alt_names.end()) { value_it = card->data.find(alt_name_it->second); } } if (value_it == card->data.end()) { if (ignore_field_not_found) return nullptr; throw ScriptError(_ERROR_1_("no field with name", key_name)); } return value_it->get(); } static void set_container(Value* container, ScriptValueP& value, String key_name) { // set the given value into the container if (TextValue* tvalue = dynamic_cast(container)) { tvalue->value = value->toString(); } else if (ChoiceValue* cvalue = dynamic_cast(container)) { cvalue->value = value->toString(); } else if (PackageChoiceValue* pvalue = dynamic_cast(container)) { pvalue->package_name = value->toString(); } else if (ColorValue* cvalue = dynamic_cast(container)) { cvalue->value = value->toColor(); } else if (ImageValue* ivalue = dynamic_cast(container)) { wxFileName fname(static_cast(value.get())->toString()); ivalue->filename = LocalFileName::fromReadString(fname.GetName(), ""); } else { throw ScriptError(_ERROR_1_("can't set value", key_name)); } } static bool set_builtin_container(GameP& game, CardP& card, ScriptValueP& value, String key_name, bool ignore_field_not_found) { // check if the given value is for a built-in field, if found set it and return true key_name = unified_form(key_name); if (key_name == _("notes") || key_name == _("note")) { card->notes = value->toString(); return true; } else if (key_name == _("style") || key_name == _("stylesheet") || key_name == _("template")) { if (trim(value->toString()) != wxEmptyString) { card->stylesheet = StyleSheet::byGameAndName(*game, value->toString()); if (card->stylesheet) card->styling_data.init(card->stylesheet->styling_fields); } return true; } //else if (key_name == _("id") || key_name == _("uid")) { // card->uid = value->toString(); // return true; //} //else if (key_name == _("linked_card") || key_name == _("linked_card_1")) { // card->linked_card_1 = value->toString(); // return true; //} //else if (key_name == _("linked_card_2")) { // card->linked_card_2 = value->toString(); // return true; //} //else if (key_name == _("linked_card_3")) { // card->linked_card_3 = value->toString(); // return true; //} //else if (key_name == _("linked_card_4")) { // card->linked_card_4 = value->toString(); // return true; //} //else if (key_name == _("linked_relation") || key_name == _("linked_relation_1")) { // card->linked_relation_1 = value->toString(); // return true; //} //else if (key_name == _("linked_relation_2")) { // card->linked_relation_2 = value->toString(); // return true; //} //else if (key_name == _("linked_relation_3")) { // card->linked_relation_3 = value->toString(); // return true; //} //else if (key_name == _("linked_relation_4")) { // card->linked_relation_4 = value->toString(); // return true; //} else if (key_name == _("styling_data") || key_name == _("style_data") || key_name == _("stylesheet_data") || key_name == _("template_data") || key_name == _("styling") || key_name == _("styling_fields") || key_name == _("style_fields") || key_name == _("stylesheet_fields") || key_name == _("template_fields")) { if (value->type() != SCRIPT_COLLECTION) { throw ScriptError(_ERROR_("styling data not map")); } ScriptValueP value_it = value->makeIterator(); ScriptValueP value_key; while (ScriptValueP value_value = value_it->next(&value_key)) { assert(value_key); if (value_key == script_nil) continue; String value_key_name = value_key->toString(); IndexMap::const_iterator style_it = card->styling_data.find(value_key_name); if (style_it == card->styling_data.end()) { style_it = card->styling_data.find(value_key_name.Lower()); if (style_it == card->styling_data.end()) { if (!ignore_field_not_found) throw ScriptError(_ERROR_1_("no style field with name", value_key_name)); continue; } } Value* value_container = style_it->get(); set_container(value_container, value_value, value_key_name); card->has_styling = true; } return true; } return false; } static bool check_table_headers(GameP& game, std::vector& headers, const String& file_extension, String& missing_fields_out) { if (headers.empty()) { queue_message(MESSAGE_ERROR, _("Empty headers given")); return false; } for (int x = 0; x < headers.size(); ++x) { String key_name = headers[x]; if ( game->card_fields_alt_names.find(unified_form(key_name)) == game->card_fields_alt_names.end() || key_name == _("notes") || key_name == _("note") || key_name == _("style") || key_name == _("stylesheet") || key_name == _("template") || key_name == _("id") || key_name == _("uid") || key_name == _("multiverse_id") || key_name == _("linked_card") || key_name == _("linked_card_1") || key_name == _("linked_card_2") || key_name == _("linked_card_3") || key_name == _("linked_card_4") || key_name == _("linked_relation") || key_name == _("linked_relation_1") || key_name == _("linked_relation_2") || key_name == _("linked_relation_3") || key_name == _("linked_relation_4") || key_name == _("link_relation") || key_name == _("link_relation_1") || key_name == _("link_relation_2") || key_name == _("link_relation_3") || key_name == _("link_relation_4") ) { missing_fields_out += _("\n ") + key_name; } } return true; } static bool cards_from_table(SetP& set, vector& headers, std::vector>& table, bool ignore_field_not_found, const String& file_extension, vector& cards_out) { // ensure table is square int count = headers.size(); for (int y = 0; y < table.size(); ++y) { if (table[y].size() != count) { queue_message(MESSAGE_ERROR, _ERROR_1_("add card csv file malformed", wxString::Format(wxT("%i"), y+1))); return false; } } // produce cards from table Context& ctx = set->getContext(); ScriptValueP new_card_function = ctx.getVariable("new_card"); ScriptValueP ctx_input = ctx.getVariableOpt(SCRIPT_VAR_input); ScriptValueP ctx_ignore = ctx.getVariableOpt("ignore_field_not_found"); ctx.setVariable("ignore_field_not_found", to_script(ignore_field_not_found)); for (int y = 0; y < table.size(); ++y) { ScriptCustomCollectionP field_map = make_intrusive(); for (int x = 0; x < count; ++x) { // check if value is worth writing if (table[y][x] != script_nil) { field_map->key_value[headers[x]] = table[y][x]; } } ctx.setVariable(SCRIPT_VAR_input, field_map); CardP card = from_script(new_card_function->eval(ctx)); // is this a new card? if (contains(set->cards, card) || contains(cards_out, card)) { // make copy card = make_intrusive(*card); } cards_out.push_back(card); } if (ctx_input) ctx.setVariable(SCRIPT_VAR_input, ctx_input); if (ctx_ignore) ctx.setVariable("ignore_field_not_found", ctx_ignore); return true; }