CL_ShaderObject CL_ShaderObject::load(CL_GraphicContext &gc, const CL_StringRef &resource_id, CL_ResourceManager *resources) { CL_Resource resource = resources->get_resource(resource_id); CL_String filename = resource.get_element().get_attribute("file"); CL_String type = resource.get_element().get_tag_name(); CL_ShaderType shader_type; if (type == "fragment-shader") shader_type = cl_shadertype_fragment; else if (type == "vertex-shader") shader_type = cl_shadertype_vertex; else throw CL_Exception("CL_ShaderObject: Unknown shader type: " + type); CL_VirtualDirectory directory = resources->get_directory(resource); CL_IODevice file = directory.open_file(filename, CL_File::open_existing, CL_File::access_read, CL_File::share_read); int size = file.get_size(); CL_String8 source(size, 0); file.read(&source[0], size); CL_ShaderObject shader_object(gc, shader_type, CL_StringHelp::local8_to_text(source)); if (resource.get_element().get_attribute("compile", "true") == "true") if(!shader_object.compile()) throw CL_Exception(cl_format("Unable to compiler shader program %1: %2", resource_id, shader_object.get_info_log())); return shader_object; }
void CL_FontProvider_Freetype::load_font(const CL_StringRef &resource_id, CL_ResourceManager *resources) { CL_Resource resource = resources->get_resource(resource_id); if (resource.get_type() != "font") throw CL_Exception(cl_format("Resource '%1' is not of type 'font'", resource.get_name())); CL_DomElement freetype_element = resource.get_element().named_item("freetype").to_element(); if (freetype_element.is_null()) throw CL_Exception(cl_format("Font resource '%1' has no 'freetype' child element", resource.get_name())); CL_FontDescription desc; if (freetype_element.has_attribute("file")) desc.set_typeface_name(freetype_element.get_attribute("file")); else throw CL_Exception(cl_format("Font resource '%1' has no 'file' attribute", resource.get_name())); if (freetype_element.has_attribute("height")) desc.set_height(freetype_element.get_attribute_int("height", 0)); else throw CL_Exception(cl_format("Font resource '%1' has no 'height' attribute", resource.get_name())); if (freetype_element.has_attribute("average_width")) desc.set_average_width(freetype_element.get_attribute_int("average_width", 0)); if (freetype_element.has_attribute("anti_alias")) desc.set_anti_alias(freetype_element.get_attribute_bool("anti_alias", true)); if (freetype_element.has_attribute("subpixel")) desc.set_subpixel(freetype_element.get_attribute_bool("subpixel", true)); load_font(desc, resources->get_directory(resource)); }
TileMap::TileMap(CL_GraphicContext& gc, CL_ResourceManager& resmgr, const CL_String& tileset) : map_width(0), map_height(0), cur_map_x(0), cur_map_y(0) { CL_Resource res = resmgr.get_resource(tileset); if (res.get_type() != "tilemap") throw CL_Exception(cl_format("Resource %1 is not a tilemap", tileset)); CL_DomElement element = res.get_element(); levelname = element.get_attribute("name"); CL_String resource_name = element.get_attribute("resource"); map_width = element.get_attribute_int("width"); map_height = element.get_attribute_int("height"); tiles = CL_Sprite(gc, resource_name, &resmgr); float scalex, scaley; tiles.get_scale(scalex, scaley); tile_width = tiles.get_width() * scalex; tile_height = tiles.get_height() * scaley; auto layer_nodes = element.select_nodes("layer"); for (CL_DomNode& idx : layer_nodes) { CL_DomElement layer_element = idx.to_element(); CL_String layer_tiles = layer_element.get_first_child().get_node_value(); std::vector<CL_String> tile_indices = CL_StringHelp::split_text(layer_tiles, ","); MapLayer layer; layer.map.reserve(tile_indices.size()); for (auto& tile : tile_indices) layer.map.push_back(CL_StringHelp::text_to_int(tile)); layers.push_back(layer); } }
void TexturePacker::process_resource(CL_Resource &item_resource, std::vector<CL_Subtexture> &packed_sub_textures, std::map<CL_Texture, CL_String> &generated_texture_filenames, int &generated_texture_index, const CL_String &image_pathname ) { // Found a sprite resource, lets modify its content! CL_Resource resource = item_resource; // Iterate through all nodes, and remove all previous image tags CL_DomElement &element = resource.get_element(); CL_DomNode cur = element.get_first_child(); while (!cur.is_null()) { CL_DomNode next = cur.get_next_sibling(); CL_DomNode::NodeType nodeType = (CL_DomNode::NodeType)cur.get_node_type(); // Only remove the <image> tag, as we want to keep the other sprite attributes if (cur.get_node_name() == "image") element.remove_child(cur); cur = next; } // Add new image tag to resource DOM std::vector<CL_Subtexture>::size_type index, size; size = packed_sub_textures.size(); for(index = 0; index < size; ++index) { CL_Subtexture subtexture = packed_sub_textures[index]; // Try to find out if we already have created a texture-on-disk for this subtexture CL_String texture_filename; CL_Texture texture = subtexture.get_texture(); std::map<CL_Texture, CL_String>::iterator it; it = generated_texture_filenames.find(texture); if(it == generated_texture_filenames.end()) { // Texture not found, generate a filename and dump texture to disk texture_filename = cl_format("texture%1.png", ++generated_texture_index); CL_PNGProvider::save(texture.get_pixeldata(), image_pathname + texture_filename); generated_texture_filenames[texture] = texture_filename; } else { // Previously dumped textures, lets reuse the filename texture_filename = (*it).second; } // Add <grid> DOM element CL_DomElement new_grid_element = element.get_owner_document().create_element("grid"); new_grid_element.set_attribute("pos", cl_format("%1,%2", subtexture.get_geometry().left + last_border_size, subtexture.get_geometry().top + last_border_size)); new_grid_element.set_attribute("size", cl_format("%1,%2", subtexture.get_geometry().get_width()- last_border_size*2, subtexture.get_geometry().get_height()- last_border_size*2)); // Add <image> DOM element CL_DomElement new_image_element = element.get_owner_document().create_element("image"); new_image_element.set_attribute("file", texture_filename); new_image_element.append_child(new_grid_element); // Add <image> element under <sprite> element element.append_child(new_image_element); } }
CL_String CL_ResourceManager::get_string_resource( const CL_String &resource_id, const CL_StringRef &default_value) { if (!resource_exists(resource_id)) return default_value; CL_Resource resource = get_resource(resource_id); return resource.get_element().get_attribute("value"); }
int CL_ResourceManager::get_integer_resource( const CL_String &resource_id, int default_value) { if (!resource_exists(resource_id)) return default_value; CL_Resource resource = get_resource(resource_id); return CL_StringHelp::text_to_int(resource.get_element().get_attribute("value")); }
CL_ResourceData_CollisionOutline::CL_ResourceData_CollisionOutline(CL_Resource &resource) { CL_String filename = resource.get_element().get_attribute("file"); int alpha_limit = CL_StringHelp::text_to_int( (resource.get_element().get_attribute("alpha_value", "128"))); CL_String accuracy_str = resource.get_element().get_attribute("accuracy", "medium"); CL_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; CL_CollisionOutline_Generic *outline; if (filename.length() >= 3 && filename.substr(filename.length()-3, 3) == "out" ) { outline = new CL_CollisionOutline_Generic( new CL_OutlineProviderFile(filename, resource.get_manager().get_directory(resource)), accuracy_raw); } else { CL_PixelBuffer pbuf = CL_ImageProviderFactory::load(filename, resource.get_manager().get_directory(resource), ""); outline = new CL_CollisionOutline_Generic( new CL_OutlineProviderBitmap(pbuf, alpha_limit), accuracy ); } CL_CollisionOutline *collision_outline_tmp = new CL_CollisionOutline(outline->contours, outline->width, outline->height); collision_outline = *collision_outline_tmp; delete collision_outline_tmp; collision_outline.calculate_radius(); delete outline; }
CL_Sprite::CL_Sprite(CL_GraphicContext &gc, const CL_StringRef &resource_id, CL_ResourceManager *resources, const CL_ImageImportDescription &import_desc) : impl(new CL_Sprite_Impl()) { CL_Resource resource = resources->get_resource(resource_id); CL_String type = resource.get_element().get_tag_name(); if (type != "sprite") throw CL_Exception(cl_format("Resource '%1' is not of type 'sprite'", resource_id)); impl->init(gc, resource_id, resources, import_desc ); }
void TileMap::load(CL_GraphicContext &gc, const CL_String &level, CL_ResourceManager &resources) { CL_Resource resource = resources.get_resource(level); if (resource.get_type() != "tilemap") throw CL_Exception(cl_format("Resource %1 is not of type tilemap!", level)); CL_DomElement element = resource.get_element(); CL_String level_name = element.get_attribute("name"); CL_String resource_name = element.get_attribute("resource"); map_width = element.get_attribute_int("width"); map_height = element.get_attribute_int("height"); cl_log_event("Debug", "Loading level %1 (%2x%3)", level_name, map_width, map_height); sprite_tiles = CL_Sprite(gc, resource_name, &resources); tile_width = sprite_tiles.get_width(); tile_height = sprite_tiles.get_height(); cl_log_event("Debug", "Loaded resource %1 with %2 tiles", resource_name, sprite_tiles.get_frame_count()); std::vector<CL_DomNode> layer_nodes = element.select_nodes("layer"); for (size_t layer_index = 0; layer_index < layer_nodes.size(); layer_index++) { CL_DomElement layer_element = layer_nodes[layer_index].to_element(); CL_String layer_name = layer_element.get_attribute("name"); CL_String layer_tiles = layer_element.get_first_child().get_node_value(); std::vector<CL_String> tile_indices = CL_StringHelp::split_text(layer_tiles, ","); TileMapLayer layer; layer.map.reserve(tile_indices.size()); for(size_t i = 0; i < tile_indices.size(); ++i) layer.map.push_back(CL_StringHelp::text_to_int(tile_indices[i])); layers.push_back(layer); cl_log_event("Debug", "Loaded layer %1 with %2 tiles", layer_name, layer.map.size()); } current_map_position_x = 0; current_map_position_y = 0; }
void TestApp::test_resources(void) { CL_Console::write_line(" Header: resource.h"); CL_Console::write_line(" Class: CL_Resource"); // Construct resource manager. This will cause sig_resource_added() to be signalled for each // resource object located in the resource file. This means ResourceApp::on_resource_added will // get called for each resource. CL_ResourceManager resources("resources.xml"); // Lets try to access some of the clanlib objects in the resource file: CL_String config_name = resources.get_string_resource("Configuration/name", ""); int config_width = resources.get_integer_resource("Configuration/width", 0 ); int config_height = resources.get_integer_resource("Configuration/height", 0 ); CL_Console::write_line(CL_String("name = ") + config_name ); CL_Console::write_line(CL_String("width = ") + CL_StringHelp::int_to_text(config_width)); CL_Console::write_line(CL_String("height = ") + CL_StringHelp::int_to_text(config_height)); // Get a list over all classes std::vector<CL_String> v = resources.get_resource_names_of_type("uclass", "Classes"); std::vector<CL_String>::iterator it; for(it = v.begin(); it != v.end(); ++it) { // Get one of our custom resources: CL_Resource resource = resources.get_resource(*it); // Its possible to access the dom element object in the resource: CL_DomElement element = resource.get_element(); int strength = CL_StringHelp::text_to_int(element.get_attribute("strength")); int magic = CL_StringHelp::text_to_int(element.get_attribute("magic")); CL_Console::write_line(CL_String("\n") + "name = " + resource.get_name()); CL_Console::write_line(CL_String("strength = ") + CL_StringHelp::int_to_text(strength)); CL_Console::write_line(CL_String("magic = ") + CL_StringHelp::int_to_text(magic) ); } }
void CL_ResourceData_TextStyler::on_load() { CL_Resource resource = get_resource(); CL_ResourceManager manager = resource.get_manager(); ts = CL_TextStyler(); std::map<std::string, CL_Font>& fnt_map = ts.get_fonts(); for ( CL_DomNode cur_node = resource.get_element().get_first_child(); !cur_node.is_null(); cur_node = cur_node.get_next_sibling()) { if (!cur_node.is_element()) continue; CL_DomElement cur_element = cur_node.to_element(); if ( cur_element.get_tag_name() == "font" && cur_element.has_attribute("name") && cur_element.has_attribute("font")) { if (manager.exists(cur_element.get_attribute("font"))) { fnt_map[cur_element.get_attribute("name")] = CL_Font(cur_element.get_attribute("font"), &manager); } else { throw CL_Error(std::string("CL_TextStyler: Unable to find sub-font named ") + cur_element.get_attribute("font")); } } else { throw CL_Error("CL_TextStyler: Unknown sub-element of a text_styler resource"); } } }
void CL_ResourceData_Font::on_load() { CL_Resource resource = get_resource(); CL_ResourceManager manager = resource.get_manager(); CL_DomElement system_element = resource.get_element().named_item("system").to_element(); CL_DomElement bitmap_element = resource.get_element().named_item("bitmap").to_element(); // First check if it's a system font if (!system_element.is_null()) { if (!system_element.has_attribute("height")) throw CL_Error("System font resource " + resource.get_name() + " has no 'height' attribute."); const std::string font_name = system_element.get_attribute("font_name"); const int height = CL_String::to_int(system_element.get_attribute("height")); int width = 0; bool bold = false; bool italic = false; bool underline = false; bool strikeout = false; if (system_element.has_attribute("width")) width = CL_String::to_int(system_element.get_attribute("width")); if (system_element.has_attribute("bold")) bold = (CL_String::to_int(system_element.get_attribute("bold")) != 0); if (system_element.has_attribute("italic")) italic = (CL_String::to_int(system_element.get_attribute("italic")) != 0); if (system_element.has_attribute("underline")) underline = (CL_String::to_int(system_element.get_attribute("underline")) != 0); if (system_element.has_attribute("strikeout")) strikeout = (CL_String::to_int(system_element.get_attribute("strikeout")) != 0); if (system_element.has_attribute("letters")) { font = CL_Font( font_name, system_element.get_attribute("letters"), height, width, bold, italic, underline, strikeout); } else { font = CL_Font( font_name, height, width, bold, italic, underline, strikeout); } } else if (!bitmap_element.is_null()) { if (!bitmap_element.has_attribute("glyphs")) throw CL_Error("Font resource " + resource.get_name() + " has no 'glyphs' attribute."); if (!bitmap_element.has_attribute("letters")) throw CL_Error("Font resource " + resource.get_name() + " has no 'letters' attribute."); //Set most values to CL_Font defaults, then we can override them with options if they exist const CL_Sprite spr_glyphs(bitmap_element.get_attribute("glyphs"), &manager); const std::string letters = bitmap_element.get_attribute("letters"); int spacelen = -1; bool monospace = false; if (bitmap_element.has_attribute("spacelen")) spacelen = CL_String::to_int(bitmap_element.get_attribute("spacelen")); if (bitmap_element.has_attribute("monospace")) monospace = (CL_String::to_int(bitmap_element.get_attribute("monospace")) != 0); font = CL_Font( spr_glyphs, letters, spacelen, monospace); } else { throw CL_Error(CL_String::format("Font resource %1 did not have a <system> or <bitmap> child element!", resource.get_name())); } if (resource.get_element().has_attribute("width_offset")) font.set_width_offset(CL_String::to_int(resource.get_element().get_attribute("width_offset"))); if (resource.get_element().has_attribute("height_offset")) font.set_height_offset(CL_String::to_int(resource.get_element().get_attribute("height_offset"))); if (resource.get_element().has_attribute("delims")) font.set_delims(resource.get_element().get_attribute("delims")); }
void CL_Sprite_Impl::init(CL_GraphicContext &gc, const CL_StringRef &resource_id, CL_ResourceManager *resources, const CL_ImageImportDescription &import_desc) { // bool pack_texture = resource.get_element().get_attribute("pack_texture", "yes") == "yes"; CL_Resource resource = resources->get_resource(resource_id); // Create sprite from sprite description CL_SpriteDescription desc(gc, resource_id, resources, import_desc ); create_textures(gc, desc); // Load base angle float work_angle = CL_StringHelp::text_to_float(resource.get_element().get_attribute("base_angle", "0")); base_angle= CL_Angle(work_angle, cl_degrees); // Load id id = CL_StringHelp::text_to_int(resource.get_element().get_attribute("id", "0")); // Load play options CL_DomNode cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) continue; CL_DomElement cur_element = cur_node.to_element(); CL_String tag_name = cur_element.get_tag_name(); // <color red="float" green="float" blue="float" alpha="float" /> if (tag_name == "color") { color.r = (float)CL_StringHelp::text_to_float(cur_element.get_attribute("red", "1.0")); color.g = (float)CL_StringHelp::text_to_float(cur_element.get_attribute("green", "1.0")); color.b = (float)CL_StringHelp::text_to_float(cur_element.get_attribute("blue", "1.0")); color.a = (float)CL_StringHelp::text_to_float(cur_element.get_attribute("alpha", "1.0")); } // <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 = CL_StringHelp::text_to_int(cur_element.get_attribute("speed", "60")); int frame_count = frames.size(); for(int i=0; i<frame_count; ++i) get_frame(i)->delay_ms = delay_ms; play_loop = ((cur_element.get_attribute("loop", "yes")) == "yes"); play_pingpong = ((cur_element.get_attribute("pingpong", "no")) == "yes"); play_backward = ((cur_element.get_attribute("direction", "forward")) == "backward"); CL_String on_finish = cur_element.get_attribute("on_finish", "blank"); if (on_finish == "first_frame") show_on_finish = CL_Sprite::show_first_frame; else if(on_finish == "last_frame") show_on_finish = CL_Sprite::show_last_frame; else show_on_finish = CL_Sprite::show_blank; } // <scale x="float" y="float /> else if (tag_name == "scale") { scale_x = CL_StringHelp::text_to_float(cur_element.get_attribute("x", "1.0")); scale_y = CL_StringHelp::text_to_float(cur_element.get_attribute("y", "1.0")); } // <translation origin="string" x="integer" y="integer" /> else if (tag_name == "translation") { CL_String hotspot = cur_element.get_attribute("origin", "top_left"); CL_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 = CL_StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = CL_StringHelp::text_to_int(cur_element.get_attribute("y", "0")); translation_origin = origin; translation_hotspot.x = xoffset; translation_hotspot.y = yoffset; } // <rotation origin="string" x="integer" y="integer" /> else if (tag_name == "rotation") { CL_String hotspot = cur_element.get_attribute("origin", "center"); CL_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 = CL_StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = CL_StringHelp::text_to_int(cur_element.get_attribute("y", "0")); rotation_origin = origin; rotation_hotspot.x = xoffset; rotation_hotspot.y = yoffset; } // <frame nr="integer" speed="integer" x="integer" y="integer" /> else if (tag_name == "frame") { int nr = CL_StringHelp::text_to_int(cur_element.get_attribute("nr", "0")); int yoffset = CL_StringHelp::text_to_int(cur_element.get_attribute("y", "0")); int xoffset = CL_StringHelp::text_to_int(cur_element.get_attribute("x", "0")); SpriteFrame *sptr = get_frame(nr); if (sptr == NULL) { throw CL_Exception("Invalid sprite frame index specified"); } if (cur_element.has_attribute("speed")) { sptr->delay_ms = CL_StringHelp::text_to_int(cur_element.get_attribute("speed", "60")); } sptr->offset = CL_Point(xoffset, yoffset); } cur_node = cur_node.get_next_sibling(); } }