void Renderer::render(surface& surf, Plateau& plateau) { surf.fill(color::black()); back.blit(surf,100,0); int blanc=0; int noir=0; for(size_t i=0;i<plateau.pions.size();i++) { for(size_t j=0;j<plateau.pions[i].size();j++) { if(plateau.pions[i][j]==Pion::black()) { black.blit(surf,100+((int)i*60),(int)j*60); noir++; } else if(plateau.pions[i][j]==Pion::white()) { white.blit(surf,100+((int)i*60),(int)j*60); blanc++; } } } if(plateau.gameFinished()) { string aff = "Joueur: " +lexical_cast<string>(blanc)+" Ordinateur: " +lexical_cast<string>(noir); surface text = thefont.render_shaded(aff,color::cyan(),color::grey()); text.blit(surf,(surf.get_width()/2)-(text.get_width()/2) ,(surf.get_height()/2)-(text.get_height()/2)); } surf.flip(); }
bool menu::imgsel_style::load_image(const std::string &img_sub) { std::string path = img_base_ + "-" + img_sub + ".png"; const surface image = image::get_image(path); img_map_[img_sub] = image; return(!image.null()); }
void textbox::append_text(const std::string& text, bool auto_scroll, const SDL_Color& color) { if(text_image_.get() == NULL) { set_text(text, color); return; } //disallow adding multi-line text to a single-line text box if(wrap_ == false && std::find_if(text.begin(),text.end(),utils::isnewline) != text.end()) { return; } const bool is_at_bottom = get_position() == get_max_position(); const wide_string& wtext = utils::string_to_wstring(text); const surface new_text = add_text_line(wtext, color); const surface new_surface = create_compatible_surface(text_image_,std::max<size_t>(text_image_->w,new_text->w),text_image_->h+new_text->h); SDL_SetAlpha(new_text.get(),0,0); SDL_SetAlpha(text_image_.get(),0,0); SDL_BlitSurface(text_image_,NULL,new_surface,NULL); SDL_Rect target = {0,text_image_->h,new_text->w,new_text->h}; SDL_BlitSurface(new_text,NULL,new_surface,&target); text_image_.assign(new_surface); text_.resize(text_.size() + wtext.size()); std::copy(wtext.begin(),wtext.end(),text_.end()-wtext.size()); set_dirty(true); update_text_cache(false); if(auto_scroll && is_at_bottom) scroll_to_bottom(); handle_text_changed(text_); }
void item_palette::draw_item(const overlay& item, surface& image, std::stringstream& tooltip_text) { std::stringstream filename; filename << item.image; if(item.image.empty()) { filename << item.halo; } image = image::get_image(filename.str()); if(image == nullptr) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for item type: '" << filename.str() << "' not found" << std::endl; image = image::get_image(game_config::images::missing); if(image == nullptr) { ERR_ED << "Placeholder image not found" << std::endl; return; } } if(image->w != item_size_ || image->h != item_size_) { image.assign(scale_surface(image, item_size_, item_size_)); } tooltip_text << item.name; }
static SDL_Cursor* get_cursor(cursor::CURSOR_TYPE type) { bool is_color = use_color_cursors(); if(cache[type] == NULL || indeterminate(cache_color[type]) || cache_color[type] != is_color) { const std::string prefix = is_color ? "cursors/" : "cursors-bw/"; const surface surf(image::get_image(prefix + (is_color ? color_images : bw_images)[type])); if (is_color) { cache[type] = SDL_CreateColorCursor(surf.get(), shift_x[type], shift_y[type]); } else { cache[type] = create_cursor(surf); } cache_color[type] = is_color; } return cache[type]; }
surface map_palette(surface s, int palette) { if(palette < 0 || palette >= palettes.size() || palettes[palette].mapping.empty()) { return s; } surface result(SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 32, SURFACE_MASK)); s = surface(SDL_ConvertSurface(s.get(), result->format, 0)); ASSERT_LOG(s->format->BytesPerPixel == 4, "SURFACE NOT IN 32bpp PIXEL FORMAT"); std::cerr << "mapping palette " << palette << "\n"; uint32_t* dst = reinterpret_cast<uint32_t*>(result->pixels); const uint32_t* src = reinterpret_cast<const uint32_t*>(s->pixels); const std::map<uint32_t,uint32_t>& mapping = palettes[palette].mapping; for(int n = 0; n != s->w*s->h; ++n) { std::map<uint32_t,uint32_t>::const_iterator i = mapping.find(*src); if(i != mapping.end()) { *dst = i->second; } else { *dst = *src; } ++src; ++dst; } return result; }
dialog_image(label *const caption, CVideo &video, surface img) : widget(video, false), surf_(img), caption_(caption) { if(!img.null()) { set_measurements(img->w, img->h); } }
void surface::blit(rectangle srcrect, surface& dst, rectangle dstrect) { SDL_Surface* ptr = get_low(); SDL_Rect srcr = rectangle::exchange_rect<SDL_Rect>(srcrect); SDL_Rect dstr = rectangle::exchange_rect<SDL_Rect>(dstrect); SDL_Surface* ptrd = dst.get_low(); if(SDL_BlitSurface(ptr,&srcr,ptrd,&dstr)<0) throw exception_sdl(); }
void run_formula(surface surf, const std::string& algo) { const hi_res_timer timer("run_formula"); const int ticks = SDL_GetTicks(); surface_formula_symbol_table table(surf); game_logic::formula f(algo, &table); bool locked = false; if(SDL_MUSTLOCK(surf.get())) { const int res = SDL_LockSurface(surf.get()); if(res == 0) { locked = true; } } std::map<Uint32, Uint32> pixel_map; Uint32* pixels = reinterpret_cast<Uint32*>(surf->pixels); Uint32* end_pixels = pixels + surf->w*surf->h; Uint32 AlphaPixel = SDL_MapRGBA(surf->format, 0x6f, 0x6d, 0x51, 0x0); int skip = 0; while(pixels != end_pixels) { if(((*pixels)&(~surf->format->Amask)) == AlphaPixel) { ++pixels; continue; } std::map<Uint32, Uint32>::const_iterator itor = pixel_map.find(*pixels); if(itor == pixel_map.end()) { pixel_callable p(surf, *pixels); Uint32 result = f.execute(p).as_int(); pixel_map[*pixels] = result; *pixels = result; } else { *pixels = itor->second; } ++pixels; } if(locked) { SDL_UnlockSurface(surf.get()); } }
static void compare_surfaces(const surface<float>& expected, const surface<float>& observed, float abs_error) { ASSERT_EQ(expected.width(), observed.width()); ASSERT_EQ(expected.height(), observed.height()); for (uint32_t x = 0; x < expected.width(); x++) { for (uint32_t y = 0; y < expected.height(); y++) { SCOPED_TRACE("(" + to_string(x) + ", " + to_string(y) + ")"); EXPECT_NEAR(expected.at(x, y), observed.at(x, y), abs_error); } } }
void effect::set_location(int x, int y) { const map_location zero_loc(0,0); int new_x = x - disp->get_location_x(zero_loc); int new_y = y - disp->get_location_y(zero_loc); if (new_x != x_ || new_y != y_) { x_ = new_x; y_ = new_y; buffer_.assign(NULL); overlayed_hexes_.clear(); } }
void terrain_palette::draw_item(const t_translation::t_terrain& terrain, surface& image, std::stringstream& tooltip_text) { const t_translation::t_terrain base_terrain = map().get_terrain_info(terrain).default_base(); //Draw default base for overlay terrains if(base_terrain != t_translation::NONE_TERRAIN) { const std::string base_filename = map().get_terrain_info(base_terrain).editor_image(); surface base_image(image::get_image(base_filename)); if(base_image == nullptr) { tooltip_text << "BASE IMAGE NOT FOUND\n"; ERR_ED << "image for terrain : '" << base_filename << "' not found" << std::endl; base_image = image::get_image(game_config::images::missing); if (base_image == nullptr) { ERR_ED << "Placeholder image not found" << std::endl; return; } } if(base_image->w != item_size_ || base_image->h != item_size_) { base_image.assign(scale_surface(base_image, item_size_, item_size_)); } } const std::string filename = map().get_terrain_info(terrain).editor_image(); image = image::get_image(filename); if(image == nullptr) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for terrain: '" << filename << "' not found" << std::endl; image = image::get_image(game_config::images::missing); if (image == nullptr) { ERR_ED << "Placeholder image not found" << std::endl; return; } } if(image->w != item_size_ || image->h != item_size_) { image.assign(scale_surface(image, item_size_, item_size_)); } tooltip_text << map().get_terrain_editor_string(terrain); if (gui_.get_draw_terrain_codes()) { tooltip_text << " " + utils::unicode_em_dash + " " << terrain; } }
surface get_surface_formula(surface input, const std::string& algo) { if(algo.empty()) { return input; } cache_key key(input, algo); surface surf = cache().get(key); if(surf.get() == NULL) { surf = input.clone(); run_formula(surf, algo); cache().put(key, surf); } return surf; }
void VisSurface::build(){ sharedInfo->release(); glGenBuffers(1, &(sharedInfo->vtx_buf_id)); glGenBuffers(1, &(sharedInfo->idx_buf_id)); glBindBuffer(GL_ARRAY_BUFFER, sharedInfo->vtx_buf_id); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sharedInfo->idx_buf_id); //prepare for data generation Vec2i dicing = sharedInfo->dicing; Vec2d dicingf = Vec2d(dicing.x - 1, dicing.y - 1); int num_floats = dicing.x * dicing.y * 3; int num_idxs = dicing.x * (dicing.y-1) * 2; float *vtxData = new float[num_floats]; unsigned int *idxData = new unsigned int[num_idxs]; //generate pt data for (int y = 0; y < dicing.y; y++){ for (int x = 0; x < dicing.x; x++){ Vec2d st = sharedInfo->region.remap(Vec2d(x,y) / dicingf); Vec3d pt = surface->eval(st); unsigned int vtx_num = (unsigned int)(dicing.x) * y + x; vtxData[3*vtx_num] = pt.x; vtxData[3*vtx_num+1] = pt.y; vtxData[3*vtx_num+2] = pt.z; if (y < dicing.y - 1){ idxData[vtx_num * 2] = vtx_num; idxData[vtx_num * 2 + 1] = vtx_num + dicing.x; } } } //TODO: normals (interleave; it's better) //send the data glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_floats, vtxData, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * num_idxs, idxData, GL_STATIC_DRAW); sharedInfo->valid = true; delete [] vtxData; delete [] idxData; }
void unit_palette::draw_item(const unit_type& u, surface& image, std::stringstream& tooltip_text) { std::stringstream filename; filename << u.image() << "~RC(" << u.flag_rgb() << '>' << team::get_side_color_id(gui_.viewing_side()) << ')'; image = image::get_image(filename.str()); if(image == nullptr) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for unit type: '" << filename.str() << "' not found" << std::endl; image = image::get_image(game_config::images::missing); if(image == nullptr) { ERR_ED << "Placeholder image not found" << std::endl; return; } } if(image->w != item_size_ || image->h != item_size_) { image.assign(scale_surface(image, item_size_, item_size_)); } tooltip_text << u.type_name(); }
int show_dialog(display& screen, surface image, const std::string& caption, const std::string& message, DIALOG_TYPE type, const std::vector<std::string>* menu_items, const std::vector<preview_pane*>* preview_panes, const std::string& text_widget_label, std::string* text_widget_text, const int text_widget_max_chars, std::vector<check_item>* options, int xloc, int yloc, const dialog_frame::style* dialog_style, std::vector<dialog_button_info>* action_buttons, const menu::sorter* sorter, menu::style* menu_style) { std::string title; if (image.null()) title = caption; const dialog::style& style = (dialog_style)? *dialog_style : dialog::default_style; CVideo &disp = screen.video(); gui::dialog d(screen, title, message, type, style); //add the components if(!image.null()) { d.set_image(image, caption); } if(menu_items) { d.set_menu( new gui::menu(disp,*menu_items,type == MESSAGE,-1,dialog::max_menu_width,sorter,menu_style,false)); } if(preview_panes) { for(unsigned int i=0; i < preview_panes->size(); ++i) { d.add_pane((*preview_panes)[i]); } } if(text_widget_text) { d.set_textbox(text_widget_label,*text_widget_text, text_widget_max_chars); } if(options) { for(unsigned int i=0; i < options->size(); ++i) { check_item& item = (*options)[i]; d.add_option(item.label, item.checked); } } if(action_buttons) { for(unsigned int i=0; i < action_buttons->size(); ++i) { d.add_button((*action_buttons)[i]); } } //enter the dialog loop d.show(xloc, yloc); //send back results if(options) { for(unsigned int i=0; i < options->size(); ++i) { (*options)[i].checked = d.option_checked(i); } } if(text_widget_text) { *text_widget_text = d.textbox_text(); } return d.result(); }
SDL_Rect draw_text_line(surface gui_surface, const SDL_Rect& area, int size, const SDL_Color& colour, const std::string& text, int x, int y, bool use_tooltips, int style) { if (gui_surface.null()) { text_surface const &u = text_cache::find(text_surface(text, size, colour, style)); SDL_Rect res = {0, 0, u.width(), u.height()}; return res; } if(area.w == 0) { // no place to draw SDL_Rect res = {0,0,0,0}; return res; } const std::string etext = make_text_ellipsis(text, size, area.w); // for the main current use, we already parsed markup surface surface(render_text(etext,size,colour,style,false)); if(surface == NULL) { SDL_Rect res = {0,0,0,0}; return res; } SDL_Rect dest; if(x!=-1) { dest.x = x; #ifdef HAVE_FRIBIDI // Oron -- Conditional, until all draw_text_line calls have fixed area parameter if(getenv("NO_RTL") == NULL) { bool is_rtl = text_cache::find(text_surface(text, size, colour, style)).is_rtl(); if(is_rtl) dest.x = area.x + area.w - surface->w - (x - area.x); } #endif } else dest.x = (area.w/2)-(surface->w/2); if(y!=-1) dest.y = y; else dest.y = (area.h/2)-(surface->h/2); dest.w = surface->w; dest.h = surface->h; if(line_width(text, size) > area.w) { tooltips::add_tooltip(dest,text); } if(dest.x + dest.w > area.x + area.w) { dest.w = area.x + area.w - dest.x; } if(dest.y + dest.h > area.y + area.h) { dest.h = area.y + area.h - dest.y; } if(gui_surface != NULL) { SDL_Rect src = dest; src.x = 0; src.y = 0; SDL_BlitSurface(surface,&src,gui_surface,&dest); } if(use_tooltips) { tooltips::add_tooltip(dest,text); } return dest; }
bool effect::render() { if(disp == NULL) { return false; } if(loc_.x != -1 && loc_.y != -1) { if(disp->shrouded(loc_)) { return false; } else { // The location of a halo is an x,y value and not a map location. // This means when a map is zoomed, the halo's won't move, // This glitch is most visible on [item] haloes. // This workaround always recalculates the location of the halo // (item haloes have a location parameter to hide them under the shroud) // and reapplies that location. // It might be optimized by storing and comparing the zoom value. set_location( disp->get_location_x(loc_) + disp->hex_size() / 2, disp->get_location_y(loc_) + disp->hex_size() / 2); } } images_.update_last_draw_time(); surf_.assign(image::get_image(current_image(),image::SCALED_TO_ZOOM)); if(surf_ == NULL) { return false; } if(orientation_ == HREVERSE || orientation_ == HVREVERSE) { surf_.assign(image::reverse_image(surf_)); } if(orientation_ == VREVERSE || orientation_ == HVREVERSE) { surf_.assign(flop_surface(surf_)); } const map_location zero_loc(0,0); const int screenx = disp->get_location_x(zero_loc); const int screeny = disp->get_location_y(zero_loc); const int xpos = x_ + screenx - surf_->w/2; const int ypos = y_ + screeny - surf_->h/2; SDL_Rect rect = create_rect(xpos, ypos, surf_->w, surf_->h); rect_ = rect; SDL_Rect clip_rect = disp->map_outside_area(); // If rendered the first time, need to determine the area affected. // If a halo changes size, it is not updated. if(overlayed_hexes_.empty()) { rect_of_hexes hexes = disp->hexes_under_rect(rect); rect_of_hexes::iterator i = hexes.begin(), end = hexes.end(); for (;i != end; ++i) { overlayed_hexes_.push_back(*i); } } if(rects_overlap(rect,clip_rect) == false) { buffer_.assign(NULL); return false; } surface screen = disp->get_screen_surface(); const clip_rect_setter clip_setter(screen, &clip_rect); if(buffer_ == NULL || buffer_->w != rect.w || buffer_->h != rect.h) { SDL_Rect rect = rect_; buffer_.assign(get_surface_portion(screen,rect)); } else { SDL_Rect rect = rect_; sdl_blit(screen,&rect,buffer_,NULL); } sdl_blit(surf_,NULL,screen,&rect); return true; }
void data_device::start_drag(data_source* source_, surface& origin_, surface* icon_, uint32_t serial_) { marshal(0, source_ ? source_->wl_obj() : nullptr, origin_.wl_obj(), icon_ ? icon_->wl_obj() : nullptr, serial_); }
surface(const surface& s) : surface_(s.get()) { add_surface_ref(surface_); }
void timage::draw(surface& canvas , const game_logic::map_formula_callable& variables) { DBG_GUI_D << "Image: draw.\n"; /** * @todo formulas are now recalculated every draw cycle which is a bit * silly unless there has been a resize. So to optimize we should use an * extra flag or do the calculation in a separate routine. */ const std::string& name = image_name_(variables); if(name.empty()) { DBG_GUI_D << "Image: formula returned no value, will not be drawn.\n"; return; } /* * The locator might return a different surface for every call so we can't * cache the output, also not if no formula is used. */ surface tmp(image::get_image(image::locator(name))); if(!tmp) { ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn.\n"; return; } image_.assign(make_neutral_surface(tmp)); assert(image_); src_clip_ = ::create_rect(0, 0, image_->w, image_->h); game_logic::map_formula_callable local_variables(variables); local_variables.add("image_original_width", variant(image_->w)); local_variables.add("image_original_height", variant(image_->h)); unsigned w = w_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(w) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', w = " << static_cast<int>(w) << ".").str()); unsigned h = h_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(h) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', h = " << static_cast<int>(h) << ".").str()); local_variables.add("image_width", variant(w ? w : image_->w)); local_variables.add("image_height", variant(h ? h : image_->h)); const unsigned x = x_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(x) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', x = " << static_cast<int>(x) << ".").str()); const unsigned y = y_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(y) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', y = " << static_cast<int>(y) << ".").str()); // Copy the data to local variables to avoid overwriting the originals. SDL_Rect src_clip = src_clip_; SDL_Rect dst_clip = ::create_rect(x, y, 0, 0); surface surf; // Test whether we need to scale and do the scaling if needed. if(w || h) { bool done = false; bool stretch_image = (resize_mode_ == stretch) && (!!w ^ !!h); if(!w) { if(stretch_image) { DBG_GUI_D << "Image: vertical stretch from " << image_->w << ',' << image_->h << " to a height of " << h << ".\n"; surf = stretch_surface_vertical(image_, h, false); done = true; } w = image_->w; } if(!h) { if(stretch_image) { DBG_GUI_D << "Image: horizontal stretch from " << image_->w << ',' << image_->h << " to a width of " << w << ".\n"; surf = stretch_surface_horizontal(image_, w, false); done = true; } h = image_->h; } if(!done) { if(resize_mode_ == tile) { DBG_GUI_D << "Image: tiling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; const int columns = (w + image_->w - 1) / image_->w; const int rows = (h + image_->h - 1) / image_->h; surf = create_neutral_surface(w, h); for(int x = 0; x < columns; ++x) { for(int y = 0; y < rows; ++y) { const SDL_Rect dest = ::create_rect( x * image_->w , y * image_->h , 0 , 0); blit_surface(image_, NULL, surf, &dest); } } } else { if(resize_mode_ == stretch) { ERR_GUI_D << "Image: failed to stretch image, " "fall back to scaling.\n"; } DBG_GUI_D << "Image: scaling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; surf = scale_surface(image_, w, h, false); } } src_clip.w = w; src_clip.h = h; } else { surf = image_; } if(vertical_mirror_(local_variables)) { surf = flip_surface(surf, false); } blit_surface(surf, &src_clip, canvas, &dst_clip); }
void assign(const surface& s) { assign_surface_internal(s.get()); }
int show_dialog(display& screen, surface image, const std::string& caption, const std::string& message, DIALOG_TYPE type, const std::vector<shared_string>* menu_items, const std::vector<preview_pane*>* preview_panes, const std::string& text_widget_label, std::string* text_widget_text, const int text_widget_max_chars, std::vector<check_item>* options, int xloc, int yloc, const dialog_frame::style* dialog_style, std::vector<dialog_button_info>* action_buttons, const menu::sorter* sorter, menu::style* menu_style) { std::string title; if (image.null()) title = caption; const dialog::style& style = (dialog_style)? *dialog_style : dialog::default_style; CVideo &disp = screen.video(); gui::dialog d(screen, title, message, type, style); //add the components if(!image.null()) { d.set_image(image, caption); } if(menu_items) { d.set_menu( new gui::menu(disp,*menu_items,type == MESSAGE,-1,dialog::max_menu_width,sorter,menu_style,false)); } if(preview_panes) { for(unsigned int i=0; i < preview_panes->size(); ++i) { d.add_pane((*preview_panes)[i]); } } if(text_widget_text) { d.set_textbox(text_widget_label,*text_widget_text, text_widget_max_chars); } if(options) { for(unsigned int i=0; i < options->size(); ++i) { check_item& item = (*options)[i]; d.add_option(item.label, item.checked); } } if(action_buttons) { for(unsigned int i=0; i < action_buttons->size(); ++i) { d.add_button((*action_buttons)[i]); } } //enter the dialog loop d.show(xloc, yloc); // KP: unfortunately, undrawing doesn't work now since we don't have easy access to the framebuffer pixels with openGL // so we set a global variable that the parent should redraw everything gRedraw = true; //send back results if(options) { for(unsigned int i=0; i < options->size(); ++i) { (*options)[i].checked = d.option_checked(i); } } if(text_widget_text) { *text_widget_text = d.textbox_text(); } return d.result(); }
void unit_drawer::redraw_unit (const unit & u) const { unit_animation_component & ac = u.anim_comp(); map_location loc = u.get_location(); int side = u.side(); bool hidden = u.get_hidden(); bool is_flying = u.is_flying(); map_location::DIRECTION facing = u.facing(); int hitpoints = u.hitpoints(); int max_hitpoints = u.max_hitpoints(); int movement_left = u.movement_left(); int total_movement = u.total_movement(); bool can_recruit = u.can_recruit(); bool can_advance = u.can_advance(); int experience = u.experience(); int max_experience = u.max_experience(); bool emit_zoc = u.emits_zoc(); SDL_Color hp_color=u.hp_color(); SDL_Color xp_color=u.xp_color(); std::string ellipse=u.image_ellipse(); if ( hidden || is_blindfolded || !u.is_visible_to_team(viewing_team_ref, dc, show_everything) ) { ac.clear_haloes(); if(ac.anim_) { ac.anim_->update_last_draw_time(); } return; } if (!ac.anim_) { ac.set_standing(); if (!ac.anim_) return; } if (ac.refreshing_) return; ac.refreshing_ = true; ac.anim_->update_last_draw_time(); frame_parameters params; const t_translation::terrain_code terrain = map.get_terrain(loc); const terrain_type& terrain_info = map.get_terrain_info(terrain); // do not set to 0 so we can distinguish the flying from the "not on submerge terrain" // instead use -1.0 (as in "negative depth", it will be ignored by rendering) params.submerge= is_flying ? -1.0 : terrain_info.unit_submerge(); if (u.invisible(loc, dc) && params.highlight_ratio > 0.5) { params.highlight_ratio = 0.5; } if (loc == sel_hex && params.highlight_ratio == 1.0) { params.highlight_ratio = 1.5; } int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * zoom_factor); if (is_flying && height_adjust < 0) { height_adjust = 0; } params.y -= height_adjust; params.halo_y -= height_adjust; int red = 0,green = 0,blue = 0,tints = 0; double blend_ratio = 0; // Add future colored states here if(u.poisoned()) { green += 255; blend_ratio += 0.25; tints += 1; } if(u.slowed()) { red += 191; green += 191; blue += 255; blend_ratio += 0.25; tints += 1; } if(tints > 0) { params.blend_with = disp.rgb((red/tints),(green/tints),(blue/tints)); params.blend_ratio = ((blend_ratio/tints)); } //hackish : see unit_frame::merge_parameters // we use image_mod on the primary image // and halo_mod on secondary images and all haloes params.image_mod = u.image_mods(); params.halo_mod = u.TC_image_mods(); params.image= u.default_anim_image(); if(u.incapacitated()) params.image_mod +="~GS()"; params.primary_frame = t_true; const frame_parameters adjusted_params = ac.anim_->get_current_params(params); const map_location dst = loc.get_direction(facing); const int xsrc = disp.get_location_x(loc); const int ysrc = disp.get_location_y(loc); const int xdst = disp.get_location_x(dst); const int ydst = disp.get_location_y(dst); const int x = static_cast<int>(adjusted_params.offset * xdst + (1.0-adjusted_params.offset) * xsrc) + hex_size_by_2; const int y = static_cast<int>(adjusted_params.offset * ydst + (1.0-adjusted_params.offset) * ysrc) + hex_size_by_2; bool has_halo = ac.unit_halo_ && ac.unit_halo_->valid(); if(!has_halo && !u.image_halo().empty()) { ac.unit_halo_ = halo_man.add(x, y - height_adjust, u.image_halo()+u.TC_image_mods(), map_location(-1, -1)); } if(has_halo && u.image_halo().empty()) { halo_man.remove(ac.unit_halo_); ac.unit_halo_ = halo::handle(); //halo::NO_HALO; } else if(has_halo) { halo_man.set_location(ac.unit_halo_, x, y - height_adjust); } // We draw bars only if wanted, visible on the map view bool draw_bars = ac.draw_bars_ ; if (draw_bars) { SDL_Rect unit_rect = sdl::create_rect(xsrc, ysrc +adjusted_params.y, hex_size, hex_size); draw_bars = sdl::rects_overlap(unit_rect, disp.map_outside_area()); } surface ellipse_front(nullptr); surface ellipse_back(nullptr); int ellipse_floating = 0; // Always show the ellipse for selected units if(draw_bars && (preferences::show_side_colors() || sel_hex == loc)) { if(adjusted_params.submerge > 0.0) { // The division by 2 seems to have no real meaning, // It just works fine with the current center of ellipse // and prevent a too large adjust if submerge = 1.0 ellipse_floating = static_cast<int>(adjusted_params.submerge * hex_size_by_2); } if(ellipse.empty()){ ellipse="misc/ellipse"; } if(ellipse != "none") { // check if the unit has a ZoC or can recruit const std::string nozoc = !emit_zoc ? "nozoc-" : ""; const std::string leader = can_recruit ? "leader-" : ""; const std::string selected = sel_hex == loc ? "selected-" : ""; const std::string tc = team::get_side_color_index(side); const std::string ellipse_top = formatter() << ellipse << "-" << leader << nozoc << selected << "top.png~RC(ellipse_red>" << tc << ")"; const std::string ellipse_bot = formatter() << ellipse << "-" << leader << nozoc << selected << "bottom.png~RC(ellipse_red>" << tc << ")"; // Load the ellipse parts recolored to match team color ellipse_back.assign(image::get_image(image::locator(ellipse_top), image::SCALED_TO_ZOOM)); ellipse_front.assign(image::get_image(image::locator(ellipse_bot), image::SCALED_TO_ZOOM)); } } if (ellipse_back != nullptr) { //disp.drawing_buffer_add(display::LAYER_UNIT_BG, loc, disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc, xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back); } if (ellipse_front != nullptr) { //disp.drawing_buffer_add(display::LAYER_UNIT_FG, loc, disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc, xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front); } if(draw_bars) { const image::locator* orb_img = nullptr; const surface unit_img = image::get_image(u.default_anim_image(), image::SCALED_TO_ZOOM); const int xoff = unit_img.null() ? hex_size_by_2 : (hex_size - unit_img->w)/2; const int yoff = unit_img.null() ? hex_size_by_2 : (hex_size - unit_img->h)/2; /*static*/ const image::locator partmoved_orb(game_config::images::orb + "~RC(magenta>" + preferences::partial_color() + ")" ); /*static*/ const image::locator moved_orb(game_config::images::orb + "~RC(magenta>" + preferences::moved_color() + ")" ); /*static*/ const image::locator ally_orb(game_config::images::orb + "~RC(magenta>" + preferences::allied_color() + ")" ); /*static*/ const image::locator enemy_orb(game_config::images::orb + "~RC(magenta>" + preferences::enemy_color() + ")" ); /*static*/ const image::locator unmoved_orb(game_config::images::orb + "~RC(magenta>" + preferences::unmoved_color() + ")" ); const std::string* energy_file = &game_config::images::energy; if(size_t(side) != viewing_team+1) { if(disp.team_valid() && viewing_team_ref.is_enemy(side)) { if (preferences::show_enemy_orb() && !u.incapacitated()) orb_img = &enemy_orb; else orb_img = nullptr; } else { if (preferences::show_allied_orb()) orb_img = &ally_orb; else orb_img = nullptr; } } else { if (preferences::show_moved_orb()) orb_img = &moved_orb; else orb_img = nullptr; if(playing_team == viewing_team && !u.user_end_turn()) { if (movement_left == total_movement) { if (preferences::show_unmoved_orb()) orb_img = &unmoved_orb; else orb_img = nullptr; } else if ( dc.unit_can_move(u) ) { if (preferences::show_partial_orb()) orb_img = &partmoved_orb; else orb_img = nullptr; } } } if (orb_img != nullptr) { surface orb(image::get_image(*orb_img,image::SCALED_TO_ZOOM)); disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xsrc + xoff, ysrc + yoff + adjusted_params.y, orb); } double unit_energy = 0.0; if(max_hitpoints > 0) { unit_energy = double(hitpoints)/double(max_hitpoints); } const int bar_shift = static_cast<int>(-5*zoom_factor); const int hp_bar_height = static_cast<int>(max_hitpoints * u.hp_bar_scaling()); const fixed_t bar_alpha = (loc == mouse_hex || loc == sel_hex) ? ftofxp(1.0): ftofxp(0.8); draw_bar(*energy_file, xsrc+xoff+bar_shift, ysrc+yoff+adjusted_params.y, loc, hp_bar_height, unit_energy,hp_color, bar_alpha); if(experience > 0 && can_advance) { const double filled = double(experience)/double(max_experience); const int xp_bar_height = static_cast<int>(max_experience * u.xp_bar_scaling() / std::max<int>(u.level(),1)); draw_bar(*energy_file, xsrc+xoff, ysrc+yoff+adjusted_params.y, loc, xp_bar_height, filled, xp_color, bar_alpha); } if (can_recruit) { surface crown(image::get_image(u.leader_crown(),image::SCALED_TO_ZOOM)); if(!crown.null()) { //if(bar_alpha != ftofxp(1.0)) { // crown = adjust_surface_alpha(crown, bar_alpha); //} disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xsrc+xoff, ysrc+yoff+adjusted_params.y, crown); } } for(std::vector<std::string>::const_iterator ov = u.overlays().begin(); ov != u.overlays().end(); ++ov) { const surface ov_img(image::get_image(*ov, image::SCALED_TO_ZOOM)); if(ov_img != nullptr) { disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xsrc+xoff, ysrc+yoff+adjusted_params.y, ov_img); } } } // Smooth unit movements from terrain of different elevation. // Do this separately from above so that the health bar doesn't go up and down. const t_translation::terrain_code terrain_dst = map.get_terrain(dst); const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst); int height_adjust_unit = static_cast<int>((terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) + terrain_dst_info.unit_height_adjust() * adjusted_params.offset) * zoom_factor); if (is_flying && height_adjust_unit < 0) { height_adjust_unit = 0; } params.y -= height_adjust_unit - height_adjust; params.halo_y -= height_adjust_unit - height_adjust; ac.anim_->redraw(params, halo_man); ac.refreshing_ = false; }
void radiosity_lightmap::generate(world_lightmap_access& data, const chunk_coordinates& pos, const surface& s, lightmap_hr &lightchunk, unsigned int phase) const { std::array<float, 6> irr_sun, irr_ambient, irr_artificial; vector half {0.5f, 0.5f, 0.5f}; auto lmi = std::begin(lightchunk); for (const faces& f : s) { fill(irr_sun, 0.f); fill(irr_ambient, 0.f); fill(irr_artificial, 0.f); auto surr (surroundings(f.pos, phase + 1)); for (auto sp : surr) { if (sp == f.pos) continue; auto found (find(s, sp)); if (found == s.end()) continue; auto& other (*found); for (int i = 0; i < 6; ++i) { if (!f[i]) continue; vector this_face (half + f.pos + vector(dir_vector[i]) * 0.52f); for (int j = 0; j < 6; ++j) { if (i == j || !other[j]) continue; vector that_face (half + other.pos + vector(dir_vector[j])* 0.52f); vector conn (that_face - this_face); vector norm_conn (normalize(conn)); float dp1 (dot_prod<vector>(dir_vector[j], -norm_conn)); if (dp1 <= 0) continue; float dp2 = dot_prod<vector>(dir_vector[i], norm_conn); if (dp2 <= 0) continue; float intensity = dp1 * dp2 / squared_length(conn); auto dist = std::distance(std::begin(s), found); auto& olm = lightchunk.data[dist]; irr_sun[i] += olm.sunlight * intensity; irr_ambient[i] += olm.ambient * intensity; irr_artificial[i] += olm.artificial * intensity; } } } for (int i (0); i < 6; ++i) { if (!f[i]) continue; lmi->r_sunlight = irr_sun[i] * 255.f + 0.49f; lmi->r_ambient = irr_ambient[i] * 255.f + 0.49f; lmi->r_artificial = irr_artificial[i] * 255.f + 0.49f; ++lmi; } } }
static void encode_channel(uint8_t *base_addr, const channel_block &block, const surface<float> &surf, const std::vector<plane> &planes, const std::pair<float, float> range, bool negative_line_stride) { block_iterator it(block.w, block.h, &surf); uint32_t n_blocks_in_line = (surf.width() / block.w); uint32_t n_block_lines = (surf.height() / block.h); // We need to support negative line stride. std::vector<std::pair<std::ptrdiff_t , std::ptrdiff_t >> line_offsets; for (const auto & plane : planes ) { if (negative_line_stride) { std::ptrdiff_t line_stride = -static_cast<std::ptrdiff_t>(plane.line_stride); // Each line is still left to right. line_offsets.emplace_back(line_stride, plane.size + line_stride); } else { line_offsets.emplace_back(plane.line_stride, 0); } } // We need to preprocess the sample array to support continuation samples. std::vector<sample> samples; for (std::size_t i = 0; i < block.samples.size();) { const xyuv::sample &sample = block.samples[i]; if (!sample.has_continuation) { samples.push_back(sample); ++i; } else { // Create a descriptor block containing all the bits of the samples. xyuv::sample sample_descriptor; sample_descriptor.integer_bits = 0; sample_descriptor.fractional_bits = 0; sample_descriptor.has_continuation = true; samples.push_back(sample_descriptor); size_t descriptor_pos = samples.size() -1; // Create a stack of all the bits in the sample. // We need to reverse the order of the samples to encode them correctly. std::vector<const xyuv::sample*> bit_stack; do { // Update descriptor samples[descriptor_pos].integer_bits += block.samples[i].integer_bits; samples[descriptor_pos].fractional_bits += block.samples[i].fractional_bits; bit_stack.push_back(&(block.samples[i])); } while(block.samples[i++].has_continuation); for (auto rit = bit_stack.rbegin(); rit != bit_stack.rend(); ++rit) { samples.push_back(*(*rit)); samples.back().has_continuation = true; } samples.back().has_continuation = false; } } // Finally iterate over the image for (uint32_t line = 0; line < n_block_lines; line++) { // Precompute interleaved lines uint32_t interleaved_line[3] = { get_line(line, static_cast<interleave_pattern>(0), n_block_lines), get_line(line, static_cast<interleave_pattern>(1), n_block_lines), get_line(line, static_cast<interleave_pattern>(2), n_block_lines), }; for (uint32_t b = 0; b < n_blocks_in_line; b++) { for (std::size_t s = 0; s < samples.size(); ) { uint8_t integer_bits = samples[s].integer_bits; uint8_t fractional_bits = samples[s].fractional_bits; float value = *it.advance(); unorm_t unorm = to_unorm(value, integer_bits, fractional_bits, range); // If we hit a continuation block here, it means that we have the // Total bits descriptor and should skip it for the purpose of actual storing. if (samples[s].has_continuation) { s++; } do { const xyuv::sample &sample = samples[s]; uint8_t * ptr_to_line = // Start with offset to frame base_addr + // Add offset to lowest byte in plane. planes[sample.plane].base_offset + // Add the size of the plane if applicable. line_offsets[sample.plane].second + // Add offset to current line. interleaved_line[static_cast<uint32_t>(planes[sample.plane].interleave_mode)] * line_offsets[sample.plane].first; // Read bits written bits from LSb fractional to MSb integer bit. write_bits( ptr_to_line, b * planes[sample.plane].block_stride + sample.offset, sample.integer_bits + sample.fractional_bits, unorm); } while (samples[s++].has_continuation); } } } }
bool operator<(const surface& a, const surface& b) { return a.get() < b.get(); }