CollisionOutline CollisionOutline::load(const std::string &id, const XMLResourceDocument &doc) { XMLResourceNode resource = doc.get_resource(id); if (resource.get_type() != "collisionoutline") throw Exception(string_format("Resource '%1' is not of type 'collisionoutline'", id)); std::string filename = resource.get_element().get_attribute("file"); int alpha_limit = StringHelp::text_to_int( (resource.get_element().get_attribute("alpha_value", "128"))); std::string accuracy_str = resource.get_element().get_attribute("accuracy", "medium"); OutlineAccuracy accuracy; if(accuracy_str == "high") accuracy = accuracy_high; else if(accuracy_str == "medium") accuracy = accuracy_medium; else if(accuracy_str == "low") accuracy = accuracy_low; else if(accuracy_str == "poor") accuracy = accuracy_poor; else accuracy = accuracy_raw; if (filename.length() >= 3 && filename.substr(filename.length()-3, 3) == "out" ) { IODevice file = resource.get_file_system().open_file(PathHelp::combine(resource.get_base_path(), filename)); OutlineProviderFile outline_provider(file); return CollisionOutline(outline_provider.get_contours(), outline_provider.get_size(), accuracy_raw); } else { PixelBuffer pbuf = ImageProviderFactory::load(PathHelp::combine(resource.get_base_path(), filename), resource.get_file_system(), ""); OutlineProviderBitmap outline_provider(pbuf, alpha_limit); return CollisionOutline(outline_provider.get_contours(), outline_provider.get_size(), accuracy); } }
Texture Texture::load(GraphicContext &gc, const std::string &id, const XMLResourceDocument &doc, const ImageImportDescription &import_desc) { XMLResourceNode resource = doc.get_resource(id); std::string type = resource.get_type(); if (type != "texture") throw Exception(string_format("Resource '%1' is not of type 'texture'", id)); std::string filename = resource.get_element().get_attribute("file"); FileSystem fs = resource.get_file_system(); Texture2D texture(gc, PathHelp::combine(resource.get_base_path(), filename), fs, import_desc); return Resource<Texture>(texture); }
Sprite Sprite::load(Canvas &canvas, const std::string &id, const XMLResourceDocument &doc) { Sprite sprite(canvas); XMLResourceNode resource = doc.get_resource(id); if (resource.get_type() != "sprite") throw Exception(string_format("Resource '%1' is not of type 'sprite'", id)); // Load base angle float work_angle = StringHelp::text_to_float(resource.get_element().get_attribute("base_angle", "0")); sprite.set_base_angle(Angle(work_angle, angle_degrees)); // Load id sprite.set_id(StringHelp::text_to_int(resource.get_element().get_attribute("id", "0"))); // Load play options DomNode cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); if (tag_name == "image" || tag_name == "image-file") { if (cur_element.has_attribute("fileseq")) { int start_index = 0; if (cur_element.has_attribute("start_index")) start_index = StringHelp::text_to_int(cur_element.get_attribute("start_index")); int skip_index = 1; if (cur_element.has_attribute("skip_index")) skip_index = StringHelp::text_to_int(cur_element.get_attribute("skip_index")); int leading_zeroes = 0; if (cur_element.has_attribute("leading_zeroes")) leading_zeroes = StringHelp::text_to_int(cur_element.get_attribute("leading_zeroes")); std::string prefix = cur_element.get_attribute("fileseq"); std::string suffix = "." + PathHelp::get_extension(prefix); prefix.erase(prefix.length() - suffix.length(), prefix.length()); //remove the extension FileSystem fs = resource.get_file_system(); bool found_initial = false; for (int i = start_index;; i = skip_index) { std::string file_name = prefix; std::string frame_text = StringHelp::int_to_text(i); for (int zeroes_to_add = (leading_zeroes + 1) - frame_text.length(); zeroes_to_add > 0; zeroes_to_add--) file_name = "0"; file_name = frame_text + suffix; try { Texture2D texture = Texture2D(canvas, PathHelp::combine(resource.get_base_path(), file_name), fs); sprite.add_frame(texture); found_initial = true; } catch (const Exception&) { if (!found_initial) { //must have been an error, pass it down throw; } //can't find anymore pics break; } } } else { std::string image_name = cur_element.get_attribute("file"); FileSystem fs = resource.get_file_system(); Texture2D texture = Texture2D(canvas, PathHelp::combine(resource.get_base_path(), image_name), fs); DomNode cur_child(cur_element.get_first_child()); if (cur_child.is_null()) { sprite.add_frame(texture); } else { do { DomElement cur_child_elemnt = cur_child.to_element(); if (cur_child.get_node_name() == "grid") { int xpos = 0; int ypos = 0; int xarray = 1; int yarray = 1; int array_skipframes = 0; int xspacing = 0; int yspacing = 0; int width = 0; int height = 0; std::vector<std::string> image_size = StringHelp::split_text(cur_child_elemnt.get_attribute("size"), ","); if (image_size.size() > 0) width = StringHelp::text_to_int(image_size[0]); if (image_size.size() > 1) height = StringHelp::text_to_int(image_size[1]); if (cur_child_elemnt.has_attribute("pos")) { std::vector<std::string> image_pos = StringHelp::split_text(cur_child_elemnt.get_attribute("pos"), ","); if (image_pos.size() > 0) xpos = StringHelp::text_to_int(image_pos[0]); if (image_pos.size() > 1) ypos = StringHelp::text_to_int(image_pos[1]); } if (cur_child_elemnt.has_attribute("array")) { std::vector<std::string> image_array = StringHelp::split_text(cur_child_elemnt.get_attribute("array"), ","); if (image_array.size() == 2) { xarray = StringHelp::text_to_int(image_array[0]); yarray = StringHelp::text_to_int(image_array[1]); } else { throw Exception("Resource '" + resource.get_name() + "' has incorrect array attribute, must be \"X,Y\"!"); } } if (cur_child_elemnt.has_attribute("array_skipframes")) { array_skipframes = StringHelp::text_to_int(cur_child_elemnt.get_attribute("array_skipframes")); } if (cur_child_elemnt.has_attribute("spacing")) { std::vector<std::string> image_spacing = StringHelp::split_text(cur_child_elemnt.get_attribute("spacing"), ","); xspacing = StringHelp::text_to_int(image_spacing[0]); yspacing = StringHelp::text_to_int(image_spacing[1]); } sprite.add_gridclipped_frames(canvas, texture, xpos, ypos, width, height, xarray, yarray, array_skipframes, xspacing, yspacing); } else if (cur_child.get_node_name() == "palette") { throw Exception("Resource '" + resource.get_name() + "' uses palette cutter - which is not supported anymore"); } else if (cur_child.get_node_name() == "alpha") { int xpos = 0; int ypos = 0; float trans_limit = 0.05f; if (cur_child_elemnt.has_attribute("pos")) { std::vector<std::string> image_pos = StringHelp::split_text(cur_child_elemnt.get_attribute("pos"), ","); xpos = StringHelp::text_to_int(image_pos[0]); ypos = StringHelp::text_to_int(image_pos[1]); } if (cur_child_elemnt.has_attribute("trans_limit")) { trans_limit = StringHelp::text_to_float(cur_child_elemnt.get_attribute("trans_limit")); } if (cur_child_elemnt.has_attribute("free")) { sprite.add_alphaclipped_frames_free(canvas, texture, xpos, ypos, trans_limit); } else { sprite.add_alphaclipped_frames(canvas, texture, xpos, ypos, trans_limit); } } cur_child = cur_child.get_next_sibling(); } while (!cur_child.is_null()); } } } cur_node = cur_node.get_next_sibling(); } cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); // <color red="float" green="float" blue="float" alpha="float" /> if (tag_name == "color") { Colorf color; color.r = (float)StringHelp::text_to_float(cur_element.get_attribute("red", "1.0")); color.g = (float)StringHelp::text_to_float(cur_element.get_attribute("green", "1.0")); color.b = (float)StringHelp::text_to_float(cur_element.get_attribute("blue", "1.0")); color.a = (float)StringHelp::text_to_float(cur_element.get_attribute("alpha", "1.0")); sprite.set_color(color); } // <animation speed="integer" loop="[yes,no]" pingpong="[yes,no]" direction="[backward,forward]" on_finish="[blank,last_frame,first_frame]"/> else if (tag_name == "animation") { int delay_ms = StringHelp::text_to_int(cur_element.get_attribute("speed", "60")); int frame_count = sprite.get_frame_count(); for (int i = 0; i < frame_count; ++i) sprite.set_frame_delay(i, delay_ms); sprite.set_play_loop((cur_element.get_attribute("loop", "yes")) == "yes"); sprite.set_play_pingpong((cur_element.get_attribute("pingpong", "no")) == "yes"); sprite.set_play_backward((cur_element.get_attribute("direction", "forward")) == "backward"); std::string on_finish = cur_element.get_attribute("on_finish", "blank"); if (on_finish == "first_frame") sprite.set_show_on_finish(Sprite::show_first_frame); else if (on_finish == "last_frame") sprite.set_show_on_finish(Sprite::show_last_frame); else sprite.set_show_on_finish(Sprite::show_blank); } // <scale x="float" y="float /> else if (tag_name == "scale") { float scale_x = StringHelp::text_to_float(cur_element.get_attribute("x", "1.0")); float scale_y = StringHelp::text_to_float(cur_element.get_attribute("y", "1.0")); sprite.set_scale(scale_x, scale_y); } // <translation origin="string" x="integer" y="integer" /> else if (tag_name == "translation") { std::string hotspot = cur_element.get_attribute("origin", "top_left"); Origin origin; if (hotspot == "center") origin = origin_center; else if (hotspot == "top_center") origin = origin_top_center; else if (hotspot == "top_right") origin = origin_top_right; else if (hotspot == "center_left") origin = origin_center_left; else if (hotspot == "center_right") origin = origin_center_right; else if (hotspot == "bottom_left") origin = origin_bottom_left; else if (hotspot == "bottom_center") origin = origin_bottom_center; else if (hotspot == "bottom_right") origin = origin_bottom_right; else origin = origin_top_left; int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); sprite.set_alignment(origin, xoffset, yoffset); } // <rotation origin="string" x="integer" y="integer" /> else if (tag_name == "rotation") { std::string hotspot = cur_element.get_attribute("origin", "center"); Origin origin; if (hotspot == "top_left") origin = origin_top_left; else if (hotspot == "top_center") origin = origin_top_center; else if (hotspot == "top_right") origin = origin_top_right; else if (hotspot == "center_left") origin = origin_center_left; else if (hotspot == "center_right") origin = origin_center_right; else if (hotspot == "bottom_left") origin = origin_bottom_left; else if (hotspot == "bottom_center") origin = origin_bottom_center; else if (hotspot == "bottom_right") origin = origin_bottom_right; else origin = origin_center; int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); sprite.set_rotation_hotspot(origin, xoffset, yoffset); } // <frame nr="integer" speed="integer" x="integer" y="integer" /> else if (tag_name == "frame") { int nr = StringHelp::text_to_int(cur_element.get_attribute("nr", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); if (nr < 0 || nr >= sprite.get_frame_count()) { throw Exception("Invalid sprite frame index specified"); } if (cur_element.has_attribute("speed")) { sprite.set_frame_delay(nr, StringHelp::text_to_int(cur_element.get_attribute("speed", "60"))); } sprite.set_frame_offset(nr, Point(xoffset, yoffset)); } cur_node = cur_node.get_next_sibling(); } sprite.restart(); return sprite; }
Font Font::load(Canvas &canvas, const std::string &family_name, const FontDescription &reference_desc, FontFamily &font_family, const XMLResourceDocument &doc, std::function<Resource<Sprite>(Canvas &, const std::string &)> cb_get_sprite) { DomElement font_element; XMLResourceNode resource; resource = doc.get_resource(family_name); font_element = resource.get_element(); DomElement sprite_element = font_element.named_item("sprite").to_element(); if (!sprite_element.is_null()) { if (!sprite_element.has_attribute("glyphs")) throw Exception(string_format("Font resource %1 has no 'glyphs' attribute.", resource.get_name())); if (!sprite_element.has_attribute("letters")) throw Exception(string_format("Font resource %1 has no 'letters' attribute.", resource.get_name())); if (!cb_get_sprite) throw Exception(string_format("Font resource %1 requires a sprite loader callback specified.", resource.get_name())); Resource<Sprite> spr_glyphs = cb_get_sprite(canvas, sprite_element.get_attribute("glyphs")); const std::string &letters = sprite_element.get_attribute("letters"); int spacelen = StringHelp::text_to_int(sprite_element.get_attribute("spacelen", "-1")); bool monospace = StringHelp::text_to_bool(sprite_element.get_attribute("monospace", "false")); // Modify the default font metrics, if specified float height = 0.0f; float line_height = 0.0f; float ascent = 0.0f; float descent = 0.0f; float internal_leading = 0.0f; float external_leading = 0.0f; if (sprite_element.has_attribute("height")) height = StringHelp::text_to_float(sprite_element.get_attribute("height", "0")); if (sprite_element.has_attribute("line_height")) line_height = StringHelp::text_to_float(sprite_element.get_attribute("line_height", "0")); if (sprite_element.has_attribute("ascent")) ascent = StringHelp::text_to_float(sprite_element.get_attribute("ascent", "0")); if (sprite_element.has_attribute("descent")) descent = StringHelp::text_to_float(sprite_element.get_attribute("descent", "0")); if (sprite_element.has_attribute("internal_leading")) internal_leading = StringHelp::text_to_float(sprite_element.get_attribute("internal_leading", "0")); if (sprite_element.has_attribute("external_leading")) external_leading = StringHelp::text_to_float(sprite_element.get_attribute("external_leading", "0")); FontMetrics font_metrics(height, ascent, descent, internal_leading, external_leading, line_height, canvas.get_pixel_ratio()); font_family.add(canvas, spr_glyphs.get(), letters, spacelen, monospace, font_metrics); FontDescription desc = reference_desc.clone(); return Font(font_family, desc); } DomElement ttf_element = font_element.named_item("ttf").to_element(); if (ttf_element.is_null()) ttf_element = font_element.named_item("freetype").to_element(); if (!ttf_element.is_null()) { FontDescription desc = reference_desc.clone(); std::string filename; if (ttf_element.has_attribute("file")) { filename = PathHelp::combine(resource.get_base_path(), ttf_element.get_attribute("file")); } if (!ttf_element.has_attribute("typeface")) throw Exception(string_format("Font resource %1 has no 'typeface' attribute.", resource.get_name())); std::string font_typeface_name = ttf_element.get_attribute("typeface"); if (ttf_element.has_attribute("height")) desc.set_height(ttf_element.get_attribute_int("height", 0)); if (ttf_element.has_attribute("average_width")) desc.set_average_width(ttf_element.get_attribute_int("average_width", 0)); if (ttf_element.has_attribute("anti_alias")) desc.set_anti_alias(ttf_element.get_attribute_bool("anti_alias", true)); if (ttf_element.has_attribute("subpixel")) desc.set_subpixel(ttf_element.get_attribute_bool("subpixel", true)); if (filename.empty()) { font_family.add(font_typeface_name, desc); return Font(font_family, desc); } else { font_family.add(desc, filename, resource.get_file_system()); return Font(font_family, desc); } } throw Exception(string_format("Font resource %1 did not have a <sprite> or <ttf> child element", resource.get_name())); }
Image Image::load(Canvas &canvas, const std::string &id, const XMLResourceDocument &doc) { Image image; XMLResourceNode resource = doc.get_resource(id); DomNode cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); if (tag_name == "image" || tag_name == "image-file") { std::string image_name = cur_element.get_attribute("file"); Texture2D texture = Texture2D(canvas, PathHelp::combine(resource.get_base_path(), image_name), resource.get_file_system()); DomNode cur_child(cur_element.get_first_child()); if (cur_child.is_null()) { image = Image(texture, texture.get_size()); } else { do { DomElement cur_child_elemnt = cur_child.to_element(); if (cur_child.get_node_name() == "grid") { Point position; Size texture_size = texture.get_size(); Size size = texture_size; std::vector<std::string> image_size = StringHelp::split_text(cur_child_elemnt.get_attribute("size"), ","); if (image_size.size() > 0) size.width = StringHelp::text_to_int(image_size[0]); if (image_size.size() > 1) size.height = StringHelp::text_to_int(image_size[1]); if (cur_child_elemnt.has_attribute("pos")) { std::vector<std::string> image_pos = StringHelp::split_text(cur_child_elemnt.get_attribute("pos"), ","); if (image_pos.size() > 0) position.x = StringHelp::text_to_int(image_pos[0]); if (image_pos.size() > 1) position.y = StringHelp::text_to_int(image_pos[1]); } if ((size.width + position.x) > texture_size.width) size.width = (texture_size.width - position.x); if ((size.height + position.y) > texture_size.height) size.height = (texture_size.height - position.y); image = Image(texture, Rect(position, size)); } cur_child = cur_child.get_next_sibling(); } while (!cur_child.is_null()); } break; } cur_node = cur_node.get_next_sibling(); } if (image.is_null()) throw Exception("Image resource contained no frames!"); cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); // <color red="float" green="float" blue="float" alpha="float" /> if (tag_name == "color") { Colorf color; color.r = (float)StringHelp::text_to_float(cur_element.get_attribute("red", "1.0")); color.g = (float)StringHelp::text_to_float(cur_element.get_attribute("green", "1.0")); color.b = (float)StringHelp::text_to_float(cur_element.get_attribute("blue", "1.0")); color.a = (float)StringHelp::text_to_float(cur_element.get_attribute("alpha", "1.0")); image.set_color(color); } // <scale x="float" y="float /> else if (tag_name == "scale") { float scale_x = StringHelp::text_to_float(cur_element.get_attribute("x", "1.0")); float scale_y = StringHelp::text_to_float(cur_element.get_attribute("y", "1.0")); image.set_scale(scale_x, scale_y); } // <translation origin="string" x="integer" y="integer" /> else if (tag_name == "translation") { std::string hotspot = cur_element.get_attribute("origin", "top_left"); Origin origin; if (hotspot == "center") origin = origin_center; else if (hotspot == "top_center") origin = origin_top_center; else if (hotspot == "top_right") origin = origin_top_right; else if (hotspot == "center_left") origin = origin_center_left; else if (hotspot == "center_right") origin = origin_center_right; else if (hotspot == "bottom_left") origin = origin_bottom_left; else if (hotspot == "bottom_center") origin = origin_bottom_center; else if (hotspot == "bottom_right") origin = origin_bottom_right; else origin = origin_top_left; int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); // TODO Find out what is going on here... xoffset /= image.get_texture().get_texture().get_pixel_ratio(); yoffset /= image.get_texture().get_texture().get_pixel_ratio(); image.set_alignment(origin, xoffset, yoffset); } cur_node = cur_node.get_next_sibling(); } return image; }