Skip to content

Commit 7cb2d3b

Browse files
committed
bugfix(drawable): Fix duplicated terrain decals applied after call to W3DModelDraw::replaceModelConditionState (#1569)
1 parent 64f0b40 commit 7cb2d3b

File tree

3 files changed

+27
-32
lines changed

3 files changed

+27
-32
lines changed

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)