diff --git a/src/dehacked.c b/src/dehacked.c index 78120c5c4..0b89b87a2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9506,6 +9506,7 @@ struct { {"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_VERTICALFLIP",FF_VERTICALFLIP}, + {"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP}, {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 2e4ea10cc..6f039cc3a 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -50,7 +50,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 455985ddf..f07cb24d8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4636,6 +4636,8 @@ static void HWR_ProjectSprite(mobj_t *thing) unsigned rot; UINT16 flip; boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean mirrored = thing->mirrored; + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); angle_t ang; INT32 heightsec, phs; @@ -4724,6 +4726,8 @@ static void HWR_ProjectSprite(mobj_t *thing) #endif ang = R_PointToAngle (thing->x, thing->y) - mobjangle; + if (mirrored) + ang = InvAngle(ang); if (sprframe->rotate == SRF_SINGLE) { @@ -4796,6 +4800,8 @@ static void HWR_ProjectSprite(mobj_t *thing) rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); } + flip = !flip != !hflip; + if (flip) { x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 68b426f0c..f5df49bcd 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1242,6 +1242,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) //mdlframe_t *next = NULL; const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); + const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; spriteinfo_t *sprinfo; @@ -1514,7 +1515,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) #endif HWD.pfnSetShader(4); // model shader - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); } return true; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 41ec703bc..e5f6ff3cf 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2615,7 +2615,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -2708,12 +2708,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglEnable(GL_NORMALIZE); #ifdef USE_FTRANSFORM_MIRROR - // flipped is if the object is flipped + // flipped is if the object is vertically flipped + // hflipped is if the object is horizontally flipped // pos->flip is if the screen is flipped vertically // pos->mirror is if the screen is flipped horizontally // XOR all the flips together to figure out what culling to use! { - boolean reversecull = (flipped ^ pos->flip ^ pos->mirror); + boolean reversecull = (flipped ^ hflipped ^ pos->flip ^ pos->mirror); if (reversecull) pglCullFace(GL_FRONT); else @@ -2721,7 +2722,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } #else // pos->flip is if the screen is flipped too - if (flipped != pos->flip) // If either are active, but not both, invert the model's culling + if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling { pglCullFace(GL_FRONT); } @@ -2736,6 +2737,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglTranslatef(pos->x, pos->z, pos->y); if (flipped) scaley = -scaley; + if (hflipped) + scalez = -scalez; #ifdef USE_FTRANSFORM_ANGLEZ pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart @@ -2882,9 +2885,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface); } // -----------------+ diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 4d0efa9e2..129339b96 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -86,6 +86,7 @@ enum mobj_e { mobj_cvmem, mobj_standingslope, mobj_colorized, + mobj_mirrored, mobj_shadowscale }; @@ -152,6 +153,7 @@ static const char *const mobj_opt[] = { "cvmem", "standingslope", "colorized", + "mirrored", "shadowscale", NULL}; @@ -385,6 +387,9 @@ static int mobj_get(lua_State *L) case mobj_colorized: lua_pushboolean(L, mo->colorized); break; + case mobj_mirrored: + lua_pushboolean(L, mo->mirrored); + break; case mobj_shadowscale: lua_pushfixed(L, mo->shadowscale); break; @@ -713,6 +718,9 @@ static int mobj_set(lua_State *L) case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; + case mobj_mirrored: + mo->mirrored = luaL_checkboolean(L, 3); + break; case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); break; diff --git a/src/p_mobj.h b/src/p_mobj.h index dae8c8a86..c94dbd650 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -373,6 +373,7 @@ typedef struct mobj_s struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) boolean colorized; // Whether the mobj uses the rainbow colormap + boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius // WARNING: New fields must be added separately to savegame and Lua. diff --git a/src/p_pspr.h b/src/p_pspr.h index 3c10e9be4..231262beb 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -64,8 +64,10 @@ #define FF_FULLBRIGHT 0x00100000 /// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity) #define FF_VERTICALFLIP 0x00200000 +/// \brief Frame flags: Flip sprite horizontally +#define FF_HORIZONTALFLIP 0x00400000 /// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) -#define FF_PAPERSPRITE 0x00400000 +#define FF_PAPERSPRITE 0x00800000 /// \brief Frame flags - Animate: Simple stateless animation #define FF_ANIMATE 0x01000000 diff --git a/src/p_saveg.c b/src/p_saveg.c index 6f5446795..dd4ade115 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1294,8 +1294,9 @@ typedef enum MD2_CEILINGROVER = 1<<10, MD2_SLOPE = 1<<11, MD2_COLORIZED = 1<<12, - MD2_ROLLANGLE = 1<<13, - MD2_SHADOWSCALE = 1<<14, + MD2_MIRRORED = 1<<13, + MD2_ROLLANGLE = 1<<14, + MD2_SHADOWSCALE = 1<<15, } mobj_diff2_t; typedef enum @@ -1500,6 +1501,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SLOPE; if (mobj->colorized) diff2 |= MD2_COLORIZED; + if (mobj->mirrored) + diff2 |= MD2_MIRRORED; if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; if (mobj->shadowscale) @@ -1638,6 +1641,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT16(save_p, mobj->standingslope->id); if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); + if (diff2 & MD2_MIRRORED) + WRITEUINT8(save_p, mobj->mirrored); if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); if (diff2 & MD2_SHADOWSCALE) @@ -2641,6 +2646,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->standingslope = P_SlopeById(READUINT16(save_p)); if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); + if (diff2 & MD2_MIRRORED) + mobj->mirrored = READUINT8(save_p); if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); if (diff2 & MD2_SHADOWSCALE) diff --git a/src/r_things.c b/src/r_things.c index de5eb208f..d2647b811 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1367,6 +1367,8 @@ static void R_ProjectSprite(mobj_t *thing) size_t frame, rot; UINT16 flip; boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean mirrored = thing->mirrored; + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); INT32 lindex; @@ -1477,7 +1479,11 @@ static void R_ProjectSprite(mobj_t *thing) #endif if (sprframe->rotate != SRF_SINGLE || papersprite) + { ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle); + if (mirrored) + ang = InvAngle(ang); + } if (sprframe->rotate == SRF_SINGLE) { @@ -1537,6 +1543,8 @@ static void R_ProjectSprite(mobj_t *thing) } #endif + flip = !flip != !hflip; + // calculate edges of the shape if (flip) offset = spr_offset - spr_width;