Skip to content

Commit

Permalink
Fixed SIGSEGV in R_VisualRadius - do not assume that a material is av…
Browse files Browse the repository at this point in the history
…ailable

for the current sprite frame because a change to the wadfiles list (e.g., an
addon is unloaded) may result in there being no valid material.

Todo: Detect missing sprite frames and draw using a suitable replacement.
  • Loading branch information
danij-deng committed Aug 5, 2011
1 parent dadcdfe commit bec3fa1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
5 changes: 4 additions & 1 deletion doomsday/engine/portable/include/r_things.h
Expand Up @@ -213,7 +213,10 @@ extern vispsprite_t visPSprites[DDMAXPSPRITES];

material_t* R_GetMaterialForSprite(int sprite, int frame);
boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* sprinfo);
float R_VisualRadius(struct mobj_s* mo);

/// @return Radius of the mobj as it would visually appear to be.
float R_VisualRadius(struct mobj_s* mo);

float R_GetBobOffset(struct mobj_s* mo);
float R_MovementYaw(float momx, float momy);
float R_MovementPitch(float momx, float momy, float momz);
Expand Down
47 changes: 25 additions & 22 deletions doomsday/engine/portable/src/r_things.c
Expand Up @@ -567,16 +567,14 @@ void R_InitSprites(void)

material_t* R_GetMaterialForSprite(int sprite, int frame)
{
spritedef_t* sprDef;

if((unsigned) sprite >= (unsigned) numSprites)
return NULL;
sprDef = &sprites[sprite];

if(frame >= sprDef->numFrames)
return NULL;

return sprDef->spriteFrames[frame].mats[0];
if((unsigned) sprite < (unsigned) numSprites)
{
spritedef_t* sprDef = &sprites[sprite];
if(frame < sprDef->numFrames)
return sprDef->spriteFrames[frame].mats[0];
}
//Con_Message("Warning::R_GetMaterialForSprite: Invalid sprite %i and/or frame %i.\n", sprite, frame);
return NULL;
}

boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info)
Expand All @@ -590,7 +588,7 @@ boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info)

if((unsigned) sprite >= (unsigned) numSprites)
{
Con_Message("R_GetSpriteInfo: Warning, invalid sprite number %i.\n", sprite);
Con_Message("Warning::R_GetSpriteInfo: Invalid sprite number %i.\n", sprite);
return false;
}

Expand All @@ -599,6 +597,7 @@ boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info)
if(frame >= sprDef->numFrames)
{
// We have no information to return.
Con_Message("Warning::R_GetSpriteInfo: Invalid sprite frame %i.\n", frame);
memset(info, 0, sizeof(*info));
return false;
}
Expand Down Expand Up @@ -628,17 +627,14 @@ boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info)
return true;
}

/**
* @return Radius of the mobj as it would visually appear to be.
*/
float R_VisualRadius(mobj_t* mo)
{
modeldef_t* mf, *nextmf;
material_snapshot_t ms;
material_t* material;

// If models are being used, use the model's radius.
if(useModels)
{
modeldef_t* mf, *nextmf;
R_CheckModelFor(mo, &mf, &nextmf);
if(mf)
{
Expand All @@ -647,12 +643,19 @@ float R_VisualRadius(mobj_t* mo)
}
}

// Use the sprite frame's width.
// @fixme What about rotation?
Materials_Prepare(&ms, R_GetMaterialForSprite(mo->sprite, mo->frame), true,
Materials_VariantSpecificationForContext(MC_SPRITE, 0, 1, 0, 0,
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 1, -2, -1, true, true, true, false));
return ms.width / 2;
// Use the sprite frame's width?
material = R_GetMaterialForSprite(mo->sprite, mo->frame);
if(material)
{
material_snapshot_t ms;
Materials_Prepare(&ms, material, true,
Materials_VariantSpecificationForContext(MC_SPRITE, 0, 1, 0, 0,
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 1, -2, -1, true, true, true, false));
return ms.width / 2;
}

// Use the physical radius.
return mo->radius;
}

/**
Expand Down

0 comments on commit bec3fa1

Please sign in to comment.