diff --git a/src/dehacked.c b/src/dehacked.c index 349b66e7c..c641887fa 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8277,6 +8277,7 @@ struct { // Frame settings {"FF_FRAMEMASK",FF_FRAMEMASK}, + {"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP}, {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_ANIMATE",FF_ANIMATE}, {"FF_FULLBRIGHT",FF_FULLBRIGHT}, diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 56055a9dc..b80543f76 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -49,7 +49,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *stransform); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 12dfa7683..8a912e59c 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5505,6 +5505,9 @@ void HWR_ProjectSprite(mobj_t *thing) size_t lumpoff; unsigned rot; UINT8 flip; + boolean mirrored = thing->mirrored; + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + angle_t ang; const boolean papersprite = (thing->frame & FF_PAPERSPRITE); INT32 heightsec, phs; @@ -5606,6 +5609,8 @@ void HWR_ProjectSprite(mobj_t *thing) #endif ang = R_PointToAngle (interp.x, interp.y) - interp.angle; + if (mirrored) + ang = InvAngle(ang); if (sprframe->rotate == SRF_SINGLE) { @@ -5710,6 +5715,8 @@ void HWR_ProjectSprite(mobj_t *thing) this_xscale = spritexscale * this_scale; this_yscale = spriteyscale * this_scale; + + flip = !flip != !hflip; if (flip) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index b3e6b8e95..9cd077588 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1149,6 +1149,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) INT32 tics = spr->mobj->tics; //mdlframe_t *next = NULL; const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); + const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; spriteinfo_t *sprinfo; @@ -1435,7 +1436,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.y += ox * gr_viewcos; p.z += oy; - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, &Surf); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf); } } } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b69a3c951..9292f8236 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3552,7 +3552,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((char*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -3613,12 +3613,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float 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 @@ -3626,7 +3627,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float } #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); else pglCullFace(GL_BACK); @@ -3636,6 +3637,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float 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 #endif @@ -3764,9 +3767,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface); } // -----------------+ diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 06c56645f..52eda4554 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -143,6 +143,7 @@ static const udata_field_t mobj_fields[] = { FIELD(mobj_t, cvmem, udatalib_getter_int32, udatalib_setter_int32), FIELD(mobj_t, standingslope, udatalib_getter_slope, mobj_standingslope_noset), FIELD(mobj_t, colorized, udatalib_getter_boolean, udatalib_setter_boolean), + FIELD(mobj_t, mirrored, udatalib_getter_boolean, udatalib_setter_boolean), FIELD(mobj_t, rollmodel, udatalib_getter_boolean, udatalib_setter_boolean), { NULL }, }; diff --git a/src/p_mobj.h b/src/p_mobj.h index 67a579c11..d53d7e3f0 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -395,6 +395,7 @@ typedef struct mobj_s boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) 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 boolean rollmodel; // OpenGL: Should this model rotate? tic_t slamsoundtimer; diff --git a/src/p_pspr.h b/src/p_pspr.h index e74266002..5ac1d1d84 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -37,6 +37,8 @@ /// \brief Frame flags: only the frame number #define FF_FRAMEMASK 0x1ff +/// \brief Frame flags: Flip sprite horizontally +#define FF_HORIZONTALFLIP 0x400 /// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) #define FF_PAPERSPRITE 0x800 /// \brief Frame flags: Simple stateless animation diff --git a/src/p_saveg.c b/src/p_saveg.c index 530a0834c..d4e9b2f5e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1990,6 +1990,8 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->stretchslam = 0; mobj->slamsoundtimer = 0; + mobj->mirrored = 0; + mobj->z = z; mobj->floorz = floorz; mobj->ceilingz = ceilingz; diff --git a/src/r_things.c b/src/r_things.c index 6334716ce..0278bf32a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1315,9 +1315,10 @@ static void R_ProjectSprite(mobj_t *thing) size_t rot; UINT8 flip; - /*boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(thing)); + /*boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(thing));*/ + boolean mirrored = thing->mirrored; - boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored);*/ + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); INT32 lindex; @@ -1445,6 +1446,8 @@ static void R_ProjectSprite(mobj_t *thing) if (sprframe->rotate != SRF_SINGLE || papersprite) { ang = R_PointToAngle (interp.x, interp.y) - interp.angle; + if (mirrored) + ang = InvAngle(ang); if (papersprite) ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT)); } @@ -1539,6 +1542,8 @@ static void R_ProjectSprite(mobj_t *thing) spr_offset += interp.spritexoffset * flipoffset; spr_topoffset += interp.spriteyoffset * flipoffset; } + + flip = !flip != !hflip; if (flip) offset = spr_offset - spr_width;