From 52bf13367fe28cb171c7bdd391f6f1d3bdbf2346 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 16 Jun 2016 00:59:54 +0100 Subject: [PATCH 1/4] New rotation functionality. * NAMEcL refers to a frame which is seen for the entirety of an object's left side. * NAMEcR refers to a name which is seen for the entirety of an object's right side. * NAMEcLcR does both sides. * Having just a NAMEcL requires you to fill in the opposite side either with NAMEcn where n is 1 and 5 to 8 OR fill in with a NAMEcR * Switches down the centerline of the object instead of at the ANGLE_202h interval for normal sprites. * Characters were selected for 1) ease of use and 2) not getting in the way of adding support for zdoom's totally bananas 16-way sprite system at a later date if we so choose --- src/hardware/hw_main.c | 11 ++++++-- src/r_defs.h | 6 +++++ src/r_things.c | 57 ++++++++++++++++++++++++++++++++++-------- src/r_things.h | 9 +++++++ 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 35a01ffd..aba89bdc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5095,8 +5095,15 @@ static void HWR_ProjectSprite(mobj_t *thing) if (sprframe->rotate) { // choose a different rotation based on player view - ang = R_PointToAngle(thing->x, thing->y); // uses viewx,viewy - rot = (ang-thing->angle+ANGLE_202h)>>29; + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + //Fab: lumpid is the index for spritewidth,spriteoffset... tables lumpoff = sprframe->lumpid[rot]; flip = sprframe->flip & (1<= 64 || rotation > 8) + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat)); if (maxframe ==(size_t)-1 || frame > maxframe) @@ -111,8 +111,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // the lump should be used for all rotations if (sprtemp[frame].rotate == 0) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - - if (sprtemp[frame].rotate == 1) + else // Let's complain for both 1-8 and L/R rotations. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); sprtemp[frame].rotate = 0; @@ -121,15 +120,46 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].lumppat[r] = lumppat; sprtemp[frame].lumpid[r] = lumpid; } - sprtemp[frame].flip = flipped ? UINT8_MAX : 0; + sprtemp[frame].flip = flipped ? UINT8_MAX : 0; // 11111111 in binary + return; + } + + if (rotation == ROT_L || rotation == ROT_R) + { + UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0); + + // the lump should be used for half of all rotations + if (sprtemp[frame].rotate == 0) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); + else if (sprtemp[frame].rotate == 1) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + // Let's not complain about multiple L/R rotations. It's not worth the effort. + + sprtemp[frame].rotate |= ((rotation == ROT_R) ? 4 : 2); + for (r = 0; r < 4; r++) + { + if ((r != 0) || (sprtemp[frame].lumppat[rotation] == LUMPERROR)) // Only set front/back angles if they don't exist + { + sprtemp[frame].lumppat[r + rightfactor] = lumppat; + sprtemp[frame].lumpid[r + rightfactor] = lumpid; + } + } + sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R return; } // the lump is only used for one rotation if (sprtemp[frame].rotate == 0) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn); + else if (sprtemp[frame].rotate != 1) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); - sprtemp[frame].rotate = 1; + if (rotation == 0 || rotation == 4) // Front or back... + sprtemp[frame].rotate = 1; // Prevent L and R changeover + else if (rotation > 3) // Right side + sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 2)); // Continue allowing L frame changeover + else // if (rotation <= 3) // Left side + sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 4)); // Continue allowing R frame changeover // make 0 based rotation--; @@ -195,7 +225,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, frame = R_Char2Frame(lumpinfo[l].name[4]); rotation = (UINT8)(lumpinfo[l].name[5] - '0'); - if (frame >= 64 || rotation > 8) // Give an actual NAME error -_-... + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -287,7 +317,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, // only the first rotation is needed break; - case 1: + default: // must have all 8 frames for (rotation = 0; rotation < 8; rotation++) // we test the patch lump, or the id lump whatever @@ -1132,8 +1162,15 @@ static void R_ProjectSprite(mobj_t *thing) if (sprframe->rotate) { // choose a different rotation based on player view - ang = R_PointToAngle (thing->x, thing->y); - rot = (ang-thing->angle+ANGLE_202h)>>29; + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + //Fab: lumpid is the index for spritewidth,spriteoffset... tables lump = sprframe->lumpid[rot]; flip = sprframe->flip & (1< Date: Thu, 16 Jun 2016 01:20:35 +0100 Subject: [PATCH 2/4] Forgot to stage this, woops. Adds special casing to prevent the I_Error and makes the behaviour of the cL/cR more consistent in general such that it matches my description. --- src/r_things.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 4f1faae9..6e4f780b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -135,14 +135,14 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); // Let's not complain about multiple L/R rotations. It's not worth the effort. + if (sprtemp[frame].rotate == 0xff) + sprtemp[frame].rotate = 0; + sprtemp[frame].rotate |= ((rotation == ROT_R) ? 4 : 2); - for (r = 0; r < 4; r++) + for (r = 1; r < 4; r++) // Don't set for front/back frames { - if ((r != 0) || (sprtemp[frame].lumppat[rotation] == LUMPERROR)) // Only set front/back angles if they don't exist - { - sprtemp[frame].lumppat[r + rightfactor] = lumppat; - sprtemp[frame].lumpid[r + rightfactor] = lumpid; - } + sprtemp[frame].lumppat[r + rightfactor] = lumppat; + sprtemp[frame].lumpid[r + rightfactor] = lumpid; } sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R return; @@ -317,6 +317,14 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, // only the first rotation is needed break; + case 6: // (rotate & (2|4)) == (2|4) - both Left and Right rotations + case 7: + // we test to see whether the left and right slots are present + if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations", + sprname, R_Frame2Char(frame)); + break; + default: // must have all 8 frames for (rotation = 0; rotation < 8; rotation++) From f08e996e761e169033cefca99bc64febfe3c1469 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 16 Jun 2016 01:37:48 +0100 Subject: [PATCH 3/4] MI corrections --- src/r_things.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 6e4f780b..650b454e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -111,7 +111,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // the lump should be used for all rotations if (sprtemp[frame].rotate == 0) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - else // Let's complain for both 1-8 and L/R rotations. + else if (sprtemp[frame].rotate != 0xff) // Let's complain for both 1-8 and L/R rotations. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); sprtemp[frame].rotate = 0; @@ -154,6 +154,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch else if (sprtemp[frame].rotate != 1) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + // make 0 based + rotation--; + if (rotation == 0 || rotation == 4) // Front or back... sprtemp[frame].rotate = 1; // Prevent L and R changeover else if (rotation > 3) // Right side @@ -161,9 +164,6 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch else // if (rotation <= 3) // Left side sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 4)); // Continue allowing R frame changeover - // make 0 based - rotation--; - if (sprtemp[frame].lumppat[rotation] != LUMPERROR) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation); From 41b35a923f64961945c7a429ea67ecc5a3171b38 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 16 Jun 2016 14:20:03 +0100 Subject: [PATCH 4/4] Gave the new flag-based system for sprite angles actual flag names instead of relying on magic numbers. Also, I did a wee smidgen of reorganisation. --- src/hardware/hw_main.c | 20 +++++++-------- src/r_defs.h | 18 ++++++++----- src/r_things.c | 57 ++++++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index aba89bdc..5dfb2d12 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5092,14 +5092,21 @@ static void HWR_ProjectSprite(mobj_t *thing) I_Error("sprframes NULL for sprite %d\n", thing->sprite); #endif - if (sprframe->rotate) + if (sprframe->rotate == SRF_SINGLE) + { + // use single rotation for all views + rot = 0; //Fab: for vis->patch below + lumpoff = sprframe->lumpid[0]; //Fab: see note above + flip = sprframe->flip; // Will only be 0x00 or 0xFF + } + else { // choose a different rotation based on player view ang = R_PointToAngle (thing->x, thing->y) - thing->angle; - if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right rot = 6; // F7 slot - else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left rot = 2; // F3 slot else // Normal behaviour rot = (ang+ANGLE_202h)>>29; @@ -5108,13 +5115,6 @@ static void HWR_ProjectSprite(mobj_t *thing) lumpoff = sprframe->lumpid[rot]; flip = sprframe->flip & (1<patch below - lumpoff = sprframe->lumpid[0]; //Fab: see note above - flip = sprframe->flip; // Will only be 0x00 or 0xFF - } if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); diff --git a/src/r_defs.h b/src/r_defs.h index 2ff2cacf..150c3fa5 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -729,11 +729,21 @@ typedef struct #pragma pack() #endif +typedef enum +{ + SRF_SINGLE = 0, // 0-angle for all rotations + SRF_3D = 1, // Angles 1-8 + SRF_LEFT = 2, // Left side has single patch + SRF_RIGHT = 4, // Right side has single patch + SRF_2D = 6, // SRF_LEFT|SRF_RIGHT + SRF_NONE = 0xff // Initial value +} spriterotateflags_t; // SRF's up! + // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. // The base name is NNNNFx or NNNNFxFx, with x indicating the rotation, -// x = 0, 1-7. +// x = 0, 1-8, L/R // The sprite and frame specified by a thing_t is range checked at run time. // A sprite is a patch_t that is assumed to represent a three dimensional // object and may have multiple rotations predrawn. @@ -745,13 +755,9 @@ typedef struct // typedef struct { - // If false use 0 for any position. - // If L is present, (rotate & 2) == 2. - // If R is present, (rotate & 4) == 4. - // Otherwise, use 1. // Note: as eight entries are available, we might as well insert the same // name eight times. - UINT8 rotate; + UINT8 rotate; // see spriterotateflags_t above // Lump to use for view angles 0-7. lumpnum_t lumppat[8]; // lump number 16 : 16 wad : lump diff --git a/src/r_things.c b/src/r_things.c index 650b454e..1ea932b9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -109,12 +109,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (rotation == 0) { // the lump should be used for all rotations - if (sprtemp[frame].rotate == 0) + if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - else if (sprtemp[frame].rotate != 0xff) // Let's complain for both 1-8 and L/R rotations. + else if (sprtemp[frame].rotate != SRF_NONE) // Let's complain for both 1-8 and L/R rotations. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); - sprtemp[frame].rotate = 0; + sprtemp[frame].rotate = SRF_SINGLE; for (r = 0; r < 8; r++) { sprtemp[frame].lumppat[r] = lumppat; @@ -129,16 +129,20 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0); // the lump should be used for half of all rotations - if (sprtemp[frame].rotate == 0) + if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); - else if (sprtemp[frame].rotate == 1) + else if (sprtemp[frame].rotate == SRF_3D) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); // Let's not complain about multiple L/R rotations. It's not worth the effort. - if (sprtemp[frame].rotate == 0xff) - sprtemp[frame].rotate = 0; + if (sprtemp[frame].rotate == SRF_NONE) + sprtemp[frame].rotate = SRF_SINGLE; + + sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); + + if (sprtemp[frame].rotate == (SRF_3D|SRF_2D)) + sprtemp[frame].rotate = SRF_2D; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen. - sprtemp[frame].rotate |= ((rotation == ROT_R) ? 4 : 2); for (r = 1; r < 4; r++) // Don't set for front/back frames { sprtemp[frame].lumppat[r + rightfactor] = lumppat; @@ -149,20 +153,20 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch } // the lump is only used for one rotation - if (sprtemp[frame].rotate == 0) + if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn); - else if (sprtemp[frame].rotate != 1) + else if ((sprtemp[frame].rotate != SRF_3D) && (sprtemp[frame].rotate != SRF_NONE)) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); // make 0 based rotation--; if (rotation == 0 || rotation == 4) // Front or back... - sprtemp[frame].rotate = 1; // Prevent L and R changeover + sprtemp[frame].rotate = SRF_3D; // Prevent L and R changeover else if (rotation > 3) // Right side - sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 2)); // Continue allowing L frame changeover + sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover else // if (rotation <= 3) // Left side - sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 4)); // Continue allowing R frame changeover + sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover if (sprtemp[frame].lumppat[rotation] != LUMPERROR) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation); @@ -308,17 +312,16 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, { switch (sprtemp[frame].rotate) { - case 0xff: + case SRF_NONE: // no rotations were found for that frame at all I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame)); break; - case 0: + case SRF_SINGLE: // only the first rotation is needed break; - case 6: // (rotate & (2|4)) == (2|4) - both Left and Right rotations - case 7: + case SRF_2D: // both Left and Right rotations // we test to see whether the left and right slots are present if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations", @@ -1167,14 +1170,21 @@ static void R_ProjectSprite(mobj_t *thing) I_Error("R_ProjectSprite: sprframes NULL for sprite %d\n", thing->sprite); #endif - if (sprframe->rotate) + if (sprframe->rotate == SRF_SINGLE) + { + // use single rotation for all views + rot = 0; //Fab: for vis->patch below + lump = sprframe->lumpid[0]; //Fab: see note above + flip = sprframe->flip; // Will only be 0x00 or 0xFF + } + else { // choose a different rotation based on player view ang = R_PointToAngle (thing->x, thing->y) - thing->angle; - if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right rot = 6; // F7 slot - else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left rot = 2; // F3 slot else // Normal behaviour rot = (ang+ANGLE_202h)>>29; @@ -1183,13 +1193,6 @@ static void R_ProjectSprite(mobj_t *thing) lump = sprframe->lumpid[rot]; flip = sprframe->flip & (1<patch below - lump = sprframe->lumpid[0]; //Fab: see note above - flip = sprframe->flip; // Will only be 0x00 or 0xFF - } I_Assert(lump < max_spritelumps);