rework ordering of layers and animation engine to use them.

this also solves missiles not being on top. any ordering bugs should
be assigned to me
This commit is contained in:
Jérémy Rosen 2008-10-31 21:58:37 +00:00
parent 9cc216a1f4
commit 5ee43b4ae1
5 changed files with 74 additions and 36 deletions

View file

@ -989,7 +989,7 @@ void display::clear_hex_overlay(const map_location& loc)
}
}
void display::render_unit_image(int x, int y, const bool /*fake_unit*/,
void display::render_unit_image(int x, int y,const display::tdrawing_layer drawing_layer,
const int drawing_order, surface image,
bool hreverse, bool greyscale, fixed_t alpha,
Uint32 blendto, double blend_ratio, double submerged,bool vreverse)
@ -1037,9 +1037,7 @@ void display::render_unit_image(int x, int y, const bool /*fake_unit*/,
SDL_Rect srcrect = {0,0,surf->w,submerge_height};
// NOTE: There is also a LAYER_UNIT_FAKE, but don't work well
// when the fake unit move behind an other
drawing_buffer_add(LAYER_UNIT_FIRST, drawing_order, tblit(x, y, surf, srcrect));
drawing_buffer_add(drawing_layer, drawing_order, tblit(x, y, surf, srcrect));
if(submerge_height != surf->h) {
surf.assign(adjust_surface_alpha(surf,ftofxp(0.2),false));
@ -1048,7 +1046,7 @@ void display::render_unit_image(int x, int y, const bool /*fake_unit*/,
srcrect.h = surf->h-submerge_height;
y += submerge_height;
drawing_buffer_add(LAYER_UNIT_FIRST, drawing_order, tblit(x, y, surf, srcrect));
drawing_buffer_add(drawing_layer, drawing_order, tblit(x, y, surf, srcrect));
}
}

View file

@ -323,23 +323,6 @@ public:
/** Rebuild all dynamic terrain. */
void rebuild_all() { builder_.rebuild_all(); }
/**
* Draw the image of a unit at a certain location.
* x,y: pixel location on screen to draw the unit
* image: the image of the unit
* reverse: if the unit should be flipped across the x axis
* greyscale: used when the unit is stoned
* alpha: the merging to use with the background
* blendto: blend to this colour using blend_ratio
* submerged: the amount of the unit out of 1.0 that is submerged
* (presumably under water) and thus shouldn't be drawn
*/
void render_unit_image(int x, int y, const bool fake_unit,
const int drawing_order, surface image,
bool hreverse=false, bool greyscale=false,
fixed_t alpha=ftofxp(1.0), Uint32 blendto=0,
double blend_ratio=0, double submerged=0.0,bool vreverse =false);
const theme::menu* menu_pressed();
/**
@ -652,18 +635,20 @@ public:
* Layer which holds stuff that needs to be
* sorted out further, but under units.
*/
LAYER_UNIT_BG, /**< Used for the ellipse behind the unit. */
LAYER_UNIT_FIRST, /**< Reserve layeres to be selected for WML. */
LAYER_UNIT_LAST=LAYER_UNIT_FIRST+100,
LAYER_UNIT_FG, /**<
* Used for the ellipse in front of the
* unit.
*/
LAYER_UNIT_FAKE, /**< The fake unit is drawn on this layer. */
LAYER_TERRAIN_FG, /**<
LAYER_UNIT_BG = LAYER_UNIT_FIRST+10, /**< Used for the ellipse behind the unit. */
LAYER_UNIT_DEFAULT=LAYER_UNIT_FIRST+40,/**<default layer for drawing units */
LAYER_TERRAIN_FG = LAYER_UNIT_FIRST+50, /**<
* Layer for the terrain drawn in front of
* the unit.
*/
LAYER_UNIT_MOVE_DEFAULT=LAYER_UNIT_FIRST+60/**<default layer for drawing moving units */,
LAYER_UNIT_FG = LAYER_UNIT_FIRST+80, /**<
* Used for the ellipse in front of the
* unit.
*/
LAYER_UNIT_MISSILE_DEFAULT = LAYER_UNIT_FIRST+90, /**< default layer for missile frames*/
LAYER_UNIT_LAST=LAYER_UNIT_FIRST+100,
LAYER_TERRAIN_TMP_FG, /**<
* Layer which holds stuff that needs to be
* sorted out further, but on top of units.
@ -685,6 +670,23 @@ public:
*/
};
/**
* Draw the image of a unit at a certain location.
* x,y: pixel location on screen to draw the unit
* image: the image of the unit
* reverse: if the unit should be flipped across the x axis
* greyscale: used when the unit is stoned
* alpha: the merging to use with the background
* blendto: blend to this colour using blend_ratio
* submerged: the amount of the unit out of 1.0 that is submerged
* (presumably under water) and thus shouldn't be drawn
*/
void render_unit_image(int x, int y, const display::tdrawing_layer drawing_layer,
const int drawing_order, surface image,
bool hreverse=false, bool greyscale=false,
fixed_t alpha=ftofxp(1.0), Uint32 blendto=0,
double blend_ratio=0, double submerged=0.0,bool vreverse =false);
/**
* Draw text on a hex. (0.5, 0.5) is the center.
* The font size is adjusted to the zoom factor

View file

@ -450,42 +450,49 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& leading_anims = expanded_cfg.get_children("leading_anim");
for(anim_itor = leading_anims.begin(); anim_itor != leading_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="leading";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"recruit_anim");
const config::child_list& recruit_anims = expanded_cfg.get_children("recruit_anim");
for(anim_itor = recruit_anims.begin(); anim_itor != recruit_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="recruited";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"standing_anim");
const config::child_list& standing_anims = expanded_cfg.get_children("standing_anim");
for(anim_itor = standing_anims.begin(); anim_itor != standing_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="standing,default";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"idle_anim");
const config::child_list& idle_anims = expanded_cfg.get_children("idle_anim");
for(anim_itor = idle_anims.begin(); anim_itor != idle_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="idling";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"levelin_anim");
const config::child_list& levelin_anims = expanded_cfg.get_children("levelin_anim");
for(anim_itor = levelin_anims.begin(); anim_itor != levelin_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="levelin";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"levelout_anim");
const config::child_list& levelout_anims = expanded_cfg.get_children("levelout_anim");
for(anim_itor = levelout_anims.begin(); anim_itor != levelout_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="levelout";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"healing_anim");
const config::child_list& healing_anims = expanded_cfg.get_children("healing_anim");
for(anim_itor = healing_anims.begin(); anim_itor != healing_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="healing";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
(**anim_itor)["value"]=(**anim_itor)["damage"];
animations.push_back(unit_animation(**anim_itor));
}
@ -493,6 +500,7 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& healed_anims = expanded_cfg.get_children("healed_anim");
for(anim_itor = healed_anims.begin(); anim_itor != healed_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="healed";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
(**anim_itor)["value"]=(**anim_itor)["healing"];
animations.push_back(unit_animation(**anim_itor));
animations.back().sub_anims_["_healed_sound"] = particule();
@ -503,6 +511,7 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& poison_anims = expanded_cfg.get_children("poison_anim");
for(anim_itor = poison_anims.begin(); anim_itor != poison_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="poisoned";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
(**anim_itor)["value"]=(**anim_itor)["damage"];
animations.push_back(unit_animation(**anim_itor));
animations.back().sub_anims_["_poison_sound"] = particule();
@ -517,12 +526,14 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
}
(**anim_itor)["apply_to"] ="movement";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"defend");
const config::child_list& defends = expanded_cfg.get_children("defend");
for(anim_itor = defends.begin(); anim_itor != defends.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="defend";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
if(!(**anim_itor)["damage"].empty()) {
(**anim_itor)["value"]=(**anim_itor)["damage"];
animations.push_back(unit_animation(**anim_itor));
@ -547,11 +558,13 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& attack_anims = expanded_cfg.get_children("attack_anim");
for(config::child_list::const_iterator d = attack_anims.begin(); d != attack_anims.end(); ++d) {
(**d)["apply_to"] ="attack";
(**d)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
if((**d)["offset"].empty() && (**d).get_children("missile_frame").empty()) {
(**d)["offset"] ="0~0.6,0.6~0";
}
if(!(**d).get_children("missile_frame").empty()) {
if( (**d)["missile_offset"].empty())(**d)["missile_offset"] = "0~0.8";
if( (**d)["missile_layer"].empty())(**d)["missile_layer"] = lexical_cast<std::string>(display::LAYER_UNIT_MISSILE_DEFAULT-display::LAYER_UNIT_FIRST);
config tmp;
tmp["duration"]="1";
(**d).add_child("missile_frame",tmp);
@ -565,6 +578,7 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& deaths = expanded_cfg.get_children("death");
for(anim_itor = deaths.begin(); anim_itor != deaths.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="death";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
image::locator image_loc = animations.back().get_last_frame().parameters(0).image;
animations.back().add_frame(600,frame_builder().image(image_loc).duration(600).highlight("1~0:600"));
@ -579,6 +593,7 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& victory_anims = expanded_cfg.get_children("victory_anim");
for(anim_itor = victory_anims.begin(); anim_itor != victory_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="victory";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
// Always have a victory animation
@ -586,15 +601,18 @@ void unit_animation::add_anims( std::vector<unit_animation> & animations, const
const config::child_list& extra_anims = expanded_cfg.get_children("extra_anim");
for(anim_itor = extra_anims.begin(); anim_itor != extra_anims.end(); ++anim_itor) {
(**anim_itor)["apply_to"] =(**anim_itor)["flag"];
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
}
expanded_cfg = unit_animation::prepare_animation(cfg,"teleport_anim");
const config::child_list& teleports = expanded_cfg.get_children("teleport_anim");
for(anim_itor = teleports.begin(); anim_itor != teleports.end(); ++anim_itor) {
(**anim_itor)["apply_to"] ="pre_teleport";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
animations.back().unit_anim_.remove_frames_after(0);
(**anim_itor)["apply_to"] ="post_teleport";
(**anim_itor)["layer"] =lexical_cast<std::string>(display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
animations.push_back(unit_animation(**anim_itor));
animations.back().unit_anim_.remove_frames_until(0);
}

View file

@ -174,7 +174,8 @@ frame_builder::frame_builder(const config& cfg,const std::string& frame_string)
offset_(""),
submerge_(""),
x_(""),
y_("")
y_(""),
drawing_layer_("")
{
image(image::locator(cfg[frame_string+"image"]),cfg[frame_string+"image_mod"]);
image_diagonal(image::locator(cfg[frame_string+"image_diagonal"]),cfg[frame_string+"image_mod"]);
@ -204,6 +205,7 @@ frame_builder::frame_builder(const config& cfg,const std::string& frame_string)
submerge(cfg[frame_string+"submerge"]);
x(cfg[frame_string+"x"]);
y(cfg[frame_string+"y"]);
drawing_layer(cfg[frame_string+"layer"]);
}
@ -227,6 +229,7 @@ const frame_parameters frame_builder::parameters(int current_time) const
result.submerge = submerge_.get_current_element(current_time);
result.x = x_.get_current_element(current_time);
result.y = y_.get_current_element(current_time);
result.drawing_layer = drawing_layer_.get_current_element(current_time);
return result;
}
frame_builder & frame_builder::image(const image::locator image ,const std::string & image_mod)
@ -276,6 +279,7 @@ void frame_builder::recalculate_duration()
submerge_=progressive_double(submerge_.get_original(),duration_);
x_=progressive_int(x_.get_original(),duration_);
y_=progressive_int(y_.get_original(),duration_);
drawing_layer_=progressive_int(drawing_layer_.get_original(),duration_);
}
frame_builder & frame_builder::blend(const std::string& blend_ratio,const Uint32 blend_color)
{
@ -308,6 +312,11 @@ frame_builder & frame_builder::y(const std::string& y)
y_=progressive_int(y,duration_);
return *this;
}
frame_builder & frame_builder::drawing_layer(const std::string& drawing_layer)
{
drawing_layer_=progressive_int(drawing_layer,duration_);
return *this;
}
bool frame_builder::does_not_change() const
{
return halo_.does_not_change() &&
@ -318,7 +327,8 @@ bool frame_builder::does_not_change() const
offset_.does_not_change() &&
submerge_.does_not_change() &&
x_.does_not_change() &&
y_.does_not_change();
y_.does_not_change() &&
drawing_layer_.does_not_change();
}
bool frame_builder::need_update() const
{
@ -330,7 +340,8 @@ bool frame_builder::need_update() const
!offset_.does_not_change() ||
!submerge_.does_not_change() ||
!x_.does_not_change() ||
!y_.does_not_change() ) {
!y_.does_not_change() ||
!drawing_layer_.does_not_change() ) {
return true;
}
return false;
@ -379,7 +390,8 @@ void unit_frame::redraw(const int frame_time,bool first_time,const map_location
bool facing_west = direction == map_location::NORTH_WEST || direction == map_location::SOUTH_WEST;
bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST;
game_display::get_singleton()->render_unit_image(x + current_data.x- image->w/2,
y + current_data.y- image->h/2, false,
y + current_data.y- image->h/2,
(display::tdrawing_layer)(display::LAYER_UNIT_FIRST+current_data.drawing_layer),
src.get_drawing_order(), image, facing_west, false,
ftofxp(current_data.highlight_ratio), current_data.blend_with,
current_data.blend_ratio,current_data.submerge,!facing_north);
@ -567,5 +579,8 @@ const frame_parameters unit_frame::merge_parameters(int current_time,const frame
result.y = current_val.y?current_val.y:animation_val.y;
result.y += engine_val.y;
assert(engine_val.drawing_layer == 0);
result.drawing_layer = current_val.drawing_layer?current_val.drawing_layer:animation_val.drawing_layer;
return result;
}

View file

@ -83,7 +83,8 @@ class frame_parameters{
offset(0),
submerge(0.0),
x(0),
y(0)
y(0),
drawing_layer(0)
{};
image::locator image;
@ -103,6 +104,7 @@ class frame_parameters{
double submerge;
int x;
int y;
int drawing_layer;
} ;
/**
* keep most parameters in a separate class to simplify handling of large
@ -128,7 +130,8 @@ class frame_builder {
offset_(""),
submerge_(""),
x_(""),
y_("")
y_(""),
drawing_layer_("")
{};
frame_builder(const config& cfg,const std::string &frame_string = "");
/** allow easy chained modifications will raised assert if used after initialization */
@ -144,6 +147,7 @@ class frame_builder {
frame_builder & submerge(const std::string& submerge);
frame_builder & x(const std::string& x);
frame_builder & y(const std::string& y);
frame_builder & drawing_layer(const std::string& drawing_layer);
/** getters for the different parameters */
const frame_parameters parameters(int current_time) const ;
@ -169,6 +173,7 @@ class frame_builder {
progressive_double submerge_;
progressive_int x_;
progressive_int y_;
progressive_int drawing_layer_;
};