TextTileSet::TextTileSet(gl::GlContext* context, std::shared_ptr<const ft::FontFace> font_face, int min_tile_slots): m_context(context), m_font_face(std::move(font_face)), m_tiles(min_tile_slots, std::bind(&TextTileSet::on_tile_drop, this, std::placeholders::_1, std::placeholders::_2)) { compute_geometries(min_tile_slots); m_texture = std::make_unique<gl::TextureArray2d>( m_context, texture_width(), texture_height(), m_texture_layers, 1, gl::Texture::InternalPixelFormat::RGBA8); add_initial_slots(); }
void TextTileSet::add_glyph(const TileLocation& location, unsigned int character) { auto glyph = std::static_pointer_cast<const ft::BitmapGlyph>( m_font_face->get_glyph(character)); auto bitmap_data = copy_glyph_bitmap(*glyph); Rectanglei tile_location(location.bottom_left.x * texture_width(), location.bottom_left.y * texture_height(), tile_width(), tile_height()); auto bound_texture = m_context->bind_texture_array_2d(*m_texture); bound_texture.update_data(tile_location, location.layer, 1, gl::Texture::DataPixelFormat::BGRA, gl::Texture::PixelType::UByte, bitmap_data.data()); }
void con_init_display(font_t font, texture_t conback) { font_free(con_default->font); texture_put(con_default->conback); con_default->font = font; con_default->conback = conback; if (con_default->conback) { con_printf("using conback (%d x %d)\n", texture_height(con_default->conback), texture_width(con_default->conback)); } con_default->cvars = cvar_ns_new("console"); cvar_register_uint(con_default->cvars, "lines", CVAR_FLAG_SAVE_NOTDEFAULT, &con_display_lines); cvar_ns_load(con_default->cvars); }
void TextTileSet::compute_geometries(int min_slots) { auto g_character = std::static_pointer_cast<const ft::BitmapGlyph>(m_font_face->get_glyph('g')); int below_baseline = g_character->top() - g_character->rows(); if(below_baseline > 0) { below_baseline = 0; } m_vert_shift = -below_baseline; m_tile_height = m_vert_shift + m_font_face->line_height(); m_texture_layers = std::ceil(static_cast<float>(min_slots) / (tiles_per_line() * tile_lines())); m_cell_width = tile_width() / static_cast<double>(texture_width()); m_cell_height = tile_height() / static_cast<double>(texture_height()); auto tile_count = tiles_per_line() * tile_lines() * m_texture_layers; m_free_slots.resize(tile_count); m_tiles.resize(tile_count); }
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) { if (!scanline_shader && GetOptionsDB().Get<bool>("UI.system-fog-of-war")) { boost::filesystem::path shader_path = GetRootDataDir() / "default" / "shaders" / "scanlines.frag"; std::string shader_text; ReadFile(shader_path, shader_text); scanline_shader = boost::shared_ptr<ShaderProgram>( ShaderProgram::shaderProgramFactory("", shader_text)); } // get fleets std::vector<TemporaryPtr<const Fleet> > fleets; for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) { TemporaryPtr<const Fleet> fleet = GetFleet(*it); if (!fleet) { Logger().errorStream() << "FleetButton::FleetButton couldn't get fleet with id " << *it; continue; } m_fleets.push_back(*it); fleets.push_back(fleet); } // determine owner(s) of fleet(s). Only care whether or not there is more than one owner, as owner // is used to determine colouration int owner_id = ALL_EMPIRES; int multiple_owners = false; if (fleets.empty()) { // leave as ALL_EMPIRES } else if (fleets.size() == 1) { owner_id = (*fleets.begin())->Owner(); } else { owner_id = (*fleets.begin())->Owner(); // use ALL_EMPIRES if there are multiple owners (including no owner and an owner) for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet->Owner() != owner_id) { owner_id = ALL_EMPIRES; multiple_owners = true; break; } } } // get fleet colour if (multiple_owners) { SetColor(GG::CLR_WHITE); } else if (owner_id == ALL_EMPIRES) { // all ships owned by now empire bool monsters = true; // find if any ship in fleets in button is not a monster for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin(); ship_it != fleet->ShipIDs().end(); ++ship_it) { if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) { if (!ship->IsMonster()) { monsters = false; break; } } } } if (monsters) SetColor(GG::CLR_RED); else SetColor(GG::CLR_WHITE); } else { // single empire owner if (const Empire* empire = Empires().Lookup(owner_id)) SetColor(empire->Color()); else SetColor(GG::CLR_GRAY); // should never be necessary... but just in case } // select icon(s) for fleet(s) int num_ships = 0; for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet) num_ships += fleet->NumShips(); } m_size_icon = FleetSizeIcon(num_ships, size_type); m_head_icons = FleetHeadIcons(fleets, size_type); // resize to fit icon by first determining necessary size, and then resizing GG::X texture_width(0); GG::Y texture_height(0); if (!m_head_icons.empty()) { texture_width = m_head_icons.front()->DefaultWidth(); texture_height = m_head_icons.front()->DefaultHeight(); } if (m_size_icon) { texture_width = std::max(texture_width, m_size_icon->DefaultWidth()); texture_height = std::max(texture_height, m_size_icon->DefaultHeight()); } // determine if fleet icon should be rotated. this should be done if the fleet is moving along // a starlane, which is the case if the fleet is not in a system and has a valid next system GG::Pt direction_vector(GG::X(0), GG::Y(1)); // default, unrotated button orientation TemporaryPtr<const Fleet> first_fleet; if (!m_fleets.empty()) first_fleet = *fleets.begin(); if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID) { int next_sys_id = first_fleet->NextSystemID(); if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) { // fleet is not in a system and has a valid next destination, so can orient it in that direction // fleet icons might not appear on the screen in the exact place corresponding to their // actual universe position, but if they're moving along a starlane, this code will assume // their apparent position will only be different from their true position in a direction // parallel with the starlane, so the direction from their true position to their destination // position can be used to get a direction vector to orient the icon double dest_x = obj->X(), dest_y = obj->Y(); double cur_x = first_fleet->X(), cur_y = first_fleet->Y(); const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd(); GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y); GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y); direction_vector = dest - cur; } } // check for unrotated texture if (Value(direction_vector.x) == 0) { // not rotated. can do simple texture blits m_vertex_components.clear(); } else { // texture is rotated, so need some extra math // get rotated corner vetex x and y components (x1, y1, x2, y2, x3, y3, x4, y4) for texture of appropriate size m_vertex_components = VectorAlignedQuadVertices(direction_vector, Value(texture_height), Value(texture_width)); } // size icon according to texture size (average two dimensions) int diameter = static_cast<int>((Value(texture_width) + Value(texture_height)) / 2.0); Resize(GG::Pt(GG::X(diameter), GG::Y(diameter))); // get selection indicator texture m_selection_texture = ClientUI::GetTexture(ClientUI::ArtDir() / "icons" / "fleet" / "fleet_selection.png", true); }