Skip to content

Commit df6ebbd

Browse files
committed
bugfix(drawable): Fix duplicated terrain decals applied after call to W3DModelDraw::replaceModelConditionState (#1569)
1 parent ee9841b commit df6ebbd

File tree

6 files changed

+54
-64
lines changed

6 files changed

+54
-64
lines changed

Generals/Code/GameEngine/Include/GameClient/Drawable.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ class Drawable : public Thing,
603603
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
604604
void updateHiddenStatus();
605605

606+
void replaceModelConditionStateInDrawable();
607+
606608
private:
607609

608610
const Locomotor* getLocomotor() const;
@@ -686,7 +688,7 @@ class Drawable : public Thing,
686688
Bool m_instanceIsIdentity; ///< If true, instance matrix can be skipped
687689
Bool m_drawableFullyObscuredByShroud; ///<drawable is hidden by shroud/fog
688690
#ifdef DIRTY_CONDITION_FLAGS
689-
mutable Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
691+
Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
690692
#endif
691693

692694
//*******************************************

Generals/Code/GameEngine/Source/GameClient/Drawable.cpp

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,13 +3478,7 @@ DrawModule** Drawable::getDrawModules()
34783478
}
34793479
else
34803480
{
3481-
for (DrawModule** dm2 = dm; *dm2; ++dm2)
3482-
{
3483-
ObjectDrawInterface* di = (*dm2)->getObjectDrawInterface();
3484-
if (di)
3485-
di->replaceModelConditionState( m_conditionState );
3486-
}
3487-
m_isModelDirty = false;
3481+
replaceModelConditionStateInDrawable();
34883482
}
34893483
}
34903484
#endif
@@ -3510,14 +3504,7 @@ DrawModule const** Drawable::getDrawModules() const
35103504
}
35113505
else
35123506
{
3513-
// yeah, yeah, yeah... I know (srj)
3514-
for (DrawModule** dm2 = (DrawModule**)dm; *dm2; ++dm2)
3515-
{
3516-
ObjectDrawInterface* di = (*dm2)->getObjectDrawInterface();
3517-
if (di)
3518-
di->replaceModelConditionState( m_conditionState );
3519-
}
3520-
m_isModelDirty = false;
3507+
const_cast<Drawable*>(this)->replaceModelConditionStateInDrawable();
35213508
}
35223509
}
35233510
#endif
@@ -3540,12 +3527,7 @@ void Drawable::clearAndSetModelConditionFlags(const ModelConditionFlags& clr, co
35403527
#ifdef DIRTY_CONDITION_FLAGS
35413528
m_isModelDirty = true;
35423529
#else
3543-
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
3544-
{
3545-
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
3546-
if (di)
3547-
di->replaceModelConditionState( m_conditionState );
3548-
}
3530+
replaceModelConditionStateInDrawable();
35493531
#endif
35503532
}
35513533

@@ -3567,24 +3549,37 @@ void Drawable::replaceModelConditionFlags( const ModelConditionFlags &flags, Boo
35673549
// when forcing a replace we won't use dirty flags, we will immediately do an update now
35683550
if( forceReplace == TRUE )
35693551
{
3570-
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
3571-
{
3572-
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
3573-
if (di)
3574-
di->replaceModelConditionState( m_conditionState );
3575-
}
3576-
m_isModelDirty = false;
3552+
replaceModelConditionStateInDrawable();
35773553
}
35783554
else
3555+
{
35793556
m_isModelDirty = true;
3557+
}
35803558
#else
3559+
replaceModelConditionStateInDrawable();
3560+
#endif
3561+
}
3562+
3563+
//-------------------------------------------------------------------------------------------------
3564+
void Drawable::replaceModelConditionStateInDrawable()
3565+
{
3566+
// TheSuperHackers @info Set not dirty early to avoid recursive calls from within getDrawModules().
3567+
m_isModelDirty = false;
3568+
3569+
// TheSuperHackers @bugfix Remove and re-add the terrain decal before processing the individual draw
3570+
// modules, because the terrain decal is applied to the first draw module only, and the new first
3571+
// draw module may be different than before.
3572+
const TerrainDecalType terrainDecalType = getTerrainDecalType();
3573+
setTerrainDecal(TERRAIN_DECAL_NONE);
3574+
35813575
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
35823576
{
35833577
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
35843578
if (di)
35853579
di->replaceModelConditionState( m_conditionState );
35863580
}
3587-
#endif
3581+
3582+
setTerrainDecal(terrainDecalType);
35883583
}
35893584

35903585
//-------------------------------------------------------------------------------------------------

Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,8 +3082,6 @@ void W3DModelDraw::setModelState(const ModelConditionInfo* newState)
30823082
// tie in our drawable as the user data pointer in the render object
30833083
m_renderObject->Set_User_Data(draw->getDrawableInfo());
30843084

3085-
setTerrainDecal(draw->getTerrainDecalType());
3086-
30873085
//We created a new render object so we need to preserve the visibility state
30883086
//of the previous render object.
30893087
if (draw->isDrawableEffectivelyHidden())

GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,8 @@ class Drawable : public Thing,
643643
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
644644
void updateHiddenStatus();
645645

646+
void replaceModelConditionStateInDrawable();
647+
646648
private:
647649

648650
const Locomotor* getLocomotor() const;
@@ -730,7 +732,7 @@ class Drawable : public Thing,
730732
Bool m_receivesDynamicLights;
731733

732734
#ifdef DIRTY_CONDITION_FLAGS
733-
mutable Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
735+
Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
734736
#endif
735737

736738
//*******************************************

GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3984,13 +3984,7 @@ DrawModule** Drawable::getDrawModules()
39843984
}
39853985
else
39863986
{
3987-
for (DrawModule** dm2 = dm; *dm2; ++dm2)
3988-
{
3989-
ObjectDrawInterface* di = (*dm2)->getObjectDrawInterface();
3990-
if (di)
3991-
di->replaceModelConditionState( m_conditionState );
3992-
}
3993-
m_isModelDirty = false;
3987+
replaceModelConditionStateInDrawable();
39943988
}
39953989
}
39963990
#endif
@@ -4016,14 +4010,7 @@ DrawModule const** Drawable::getDrawModules() const
40164010
}
40174011
else
40184012
{
4019-
// yeah, yeah, yeah... I know (srj)
4020-
for (DrawModule** dm2 = (DrawModule**)dm; *dm2; ++dm2)
4021-
{
4022-
ObjectDrawInterface* di = (*dm2)->getObjectDrawInterface();
4023-
if (di)
4024-
di->replaceModelConditionState( m_conditionState );
4025-
}
4026-
m_isModelDirty = false;
4013+
const_cast<Drawable*>(this)->replaceModelConditionStateInDrawable();
40274014
}
40284015
}
40294016
#endif
@@ -4046,12 +4033,7 @@ void Drawable::clearAndSetModelConditionFlags(const ModelConditionFlags& clr, co
40464033
#ifdef DIRTY_CONDITION_FLAGS
40474034
m_isModelDirty = true;
40484035
#else
4049-
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
4050-
{
4051-
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
4052-
if (di)
4053-
di->replaceModelConditionState( m_conditionState );
4054-
}
4036+
replaceModelConditionStateInDrawable();
40554037
#endif
40564038
}
40574039

@@ -4073,24 +4055,37 @@ void Drawable::replaceModelConditionFlags( const ModelConditionFlags &flags, Boo
40734055
// when forcing a replace we won't use dirty flags, we will immediately do an update now
40744056
if( forceReplace == TRUE )
40754057
{
4076-
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
4077-
{
4078-
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
4079-
if (di)
4080-
di->replaceModelConditionState( m_conditionState );
4081-
}
4082-
m_isModelDirty = false;
4058+
replaceModelConditionStateInDrawable();
40834059
}
40844060
else
4061+
{
40854062
m_isModelDirty = true;
4063+
}
40864064
#else
4065+
replaceModelConditionStateInDrawable();
4066+
#endif
4067+
}
4068+
4069+
//-------------------------------------------------------------------------------------------------
4070+
void Drawable::replaceModelConditionStateInDrawable()
4071+
{
4072+
// TheSuperHackers @info Set not dirty early to avoid recursive calls from within getDrawModules().
4073+
m_isModelDirty = false;
4074+
4075+
// TheSuperHackers @bugfix Remove and re-add the terrain decal before processing the individual draw
4076+
// modules, because the terrain decal is applied to the first draw module only, and the new first
4077+
// draw module may be different than before.
4078+
const TerrainDecalType terrainDecalType = getTerrainDecalType();
4079+
setTerrainDecal(TERRAIN_DECAL_NONE);
4080+
40874081
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
40884082
{
40894083
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
40904084
if (di)
40914085
di->replaceModelConditionState( m_conditionState );
40924086
}
4093-
#endif
4087+
4088+
setTerrainDecal(terrainDecalType);
40944089
}
40954090

40964091
//-------------------------------------------------------------------------------------------------

GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,8 +3141,6 @@ void W3DModelDraw::setModelState(const ModelConditionInfo* newState)
31413141
// tie in our drawable as the user data pointer in the render object
31423142
m_renderObject->Set_User_Data(draw->getDrawableInfo());
31433143

3144-
setTerrainDecal(draw->getTerrainDecalType());
3145-
31463144
//We created a new render object so we need to preserve the visibility state
31473145
//of the previous render object.
31483146
if (draw->isDrawableEffectivelyHidden())

0 commit comments

Comments
 (0)