Skip to content

Commit bb83868

Browse files
authored
Merge pull request #85 from Andreas-W/animation_blending
(Mech Package) Animation blending, Decals FXNuggets, FXEvents, AnimationSteeringUpdate
2 parents d7fb4c4 + ea14059 commit bb83868

18 files changed

Lines changed: 1540 additions & 87 deletions

File tree

Core/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ static PoolSizeRec PoolSizes[] =
334334
{ "W3DTankDraw", 256, 32 },
335335
{ "W3DTreeDraw", 16, 16 },
336336
{ "W3DPropDraw", 16, 16 },
337+
{ "W3DDecalDraw", 16, 16 },
337338
{ "W3DTracerDraw", 64, 32 },
338339
{ "W3DTruckDraw", 128, 32 },
339340
{ "W3DTankTruckDraw", 32, 16 },
@@ -499,6 +500,7 @@ static PoolSizeRec PoolSizes[] =
499500
{ "GenericObjectCreationNugget", 632, 32 },
500501
{ "SoundFXNugget", 320, 32 },
501502
{ "TracerFXNugget", 32, 32 },
503+
{ "DecalFXNugget", 32, 32 },
502504
{ "RayEffectFXNugget", 32, 32 },
503505
{ "LightPulseFXNugget", 68, 32 },
504506
{ "ViewShakeFXNugget", 140, 32 },

Core/GameEngine/Source/GameClient/FXList.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
3131
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
3232

33+
#define DEFINE_SHADOW_NAMES
34+
3335
#include "GameClient/FXList.h"
3436

3537
#include "Common/DrawModule.h"
@@ -50,6 +52,9 @@
5052
#include "GameClient/Drawable.h"
5153
#include "GameClient/ParticleSys.h"
5254
#include "GameLogic/PartitionManager.h"
55+
#include "GameClient/Shadow.h"
56+
#include "../../../GameEngineDevice/Include/W3DDevice/GameClient/Module/W3DModelDraw.h"
57+
#include "../../../GameEngineDevice/Include/W3DDevice/GameClient/W3DShadow.h"
5358

5459
///////////////////////////////////////////////////////////////////////////////////////////////////
5560
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
@@ -467,6 +472,119 @@ class RayEffectFXNugget : public FXNugget
467472
};
468473
EMPTY_DTOR(RayEffectFXNugget)
469474

475+
476+
//-------------------------------------------------------------------------------------------------
477+
class DecalFXNugget : public FXNugget
478+
{
479+
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DecalFXNugget, "DecalFXNugget")
480+
public:
481+
482+
DecalFXNugget()
483+
{
484+
m_templateName.set("GenericDecal"); // TODO
485+
//m_templateName = AsciiString::TheEmptyString;
486+
//m_textureName = AsciiString::TheEmptyString;
487+
//m_opacity = 1.0; ///< value between 0 and 1
488+
//m_color = 0; ///< color in ARGB format. (Alpha is ignored).
489+
m_lifetime = 0;
490+
/* m_fadeOutTime = 0;
491+
m_fadeInTime = 0;
492+
m_type = 0; /// type of projection
493+
m_decalSizeX = 0.0; /// 1/(world space extent of texture in x direction)
494+
m_decalSizeY = 0.0; /// 1/(world space extent of texture in y direction)*/
495+
m_offset.x = m_offset.y = m_offset.z = 0;
496+
m_angle = 0.0;
497+
m_orientToObject = FALSE;
498+
m_randomAngle = FALSE;
499+
m_probability = 1.0f;
500+
}
501+
502+
virtual void doFXPos(const Coord3D* primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D* secondary, const Real /*overrideRadius*/, FXSurfaceInfo* /*surfaceInfo*/) const
503+
{
504+
if (m_probability <= GameClientRandomValueReal(0, 1))
505+
return;
506+
507+
if (primary)
508+
{
509+
Coord3D offset = m_offset;
510+
if (primaryMtx) {
511+
if (m_orientToObject)
512+
{
513+
adjustVector(&offset, primaryMtx);
514+
}
515+
}
516+
517+
Drawable* drawable = TheThingFactory->newDrawable(TheThingFactory->findTemplate(m_templateName));
518+
if (!drawable)
519+
return;
520+
521+
// Does it even make sense to set the matrix?
522+
if (primaryMtx && m_orientToObject)
523+
drawable->setTransformMatrix(primaryMtx);
524+
525+
Coord3D newPos;
526+
newPos.x = primary->x + offset.x;
527+
newPos.y = primary->y + offset.y;
528+
newPos.z = primary->z + offset.z;
529+
drawable->setPosition(&newPos);
530+
531+
if (m_randomAngle)
532+
drawable->setOrientation(GameClientRandomValueReal(0, PI * 2));
533+
534+
drawable->setExpirationDate(TheGameLogic->getFrame() + m_lifetime);
535+
}
536+
else
537+
{
538+
DEBUG_CRASH(("You must have a primary source for this effect"));
539+
}
540+
}
541+
542+
virtual void doFXObj(const Object* primary, const Object* secondary, FXSurfaceInfo* surfaceInfo) const
543+
{
544+
if (primary)
545+
{
546+
doFXPos(primary->getPosition(), primary->getTransformMatrix(), 0.0f, nullptr, 0.0f, surfaceInfo);
547+
}
548+
else
549+
{
550+
DEBUG_CRASH(("You must have a primary source for this effect"));
551+
}
552+
}
553+
554+
static void parse(INI* ini, void* instance, void* /*store*/, const void* /*userData*/)
555+
{
556+
static const FieldParse myFieldParse[] =
557+
{
558+
{ "DecalName", INI::parseAsciiString, nullptr, offsetof(DecalFXNugget, m_templateName) },
559+
{ "Lifetime", INI::parseDurationUnsignedInt, nullptr, offsetof(DecalFXNugget, m_lifetime) },
560+
{ "Offset", INI::parseCoord3D, nullptr, offsetof(DecalFXNugget, m_offset) },
561+
{ "Angle", INI::parseReal, nullptr, offsetof(DecalFXNugget, m_angle) },
562+
{ "RandomAngle", INI::parseBool, nullptr, offsetof(DecalFXNugget, m_randomAngle) },
563+
{ "OrientToObject", INI::parseBool, nullptr, offsetof(DecalFXNugget, m_orientToObject) },
564+
{ "Probability", INI::parseReal, nullptr, offsetof(DecalFXNugget, m_probability) },
565+
{ nullptr, nullptr, nullptr, 0 }
566+
};
567+
568+
DecalFXNugget* nugget = newInstance(DecalFXNugget);
569+
ini->initFromINI(nugget, myFieldParse);
570+
((FXList*)instance)->addFXNugget(nugget);
571+
}
572+
573+
private:
574+
AsciiString m_templateName;
575+
UnsignedInt m_lifetime;
576+
Coord3D m_offset;
577+
Real m_angle;
578+
Bool m_orientToObject;
579+
Bool m_randomAngle;
580+
581+
// spawn parameters
582+
Real m_probability;
583+
// TODO: Height/Surface, etc.
584+
};
585+
EMPTY_DTOR(DecalFXNugget)
586+
587+
470588
//-------------------------------------------------------------------------------------------------
471589
class LightPulseFXNugget : public FXNugget
472590
{
@@ -1025,6 +1143,7 @@ static const FieldParse TheFXListFieldParse[] =
10251143
{ "TerrainScorch", TerrainScorchFXNugget::parse, nullptr, 0},
10261144
{ "ParticleSystem", ParticleSystemFXNugget::parse, nullptr, 0},
10271145
{ "FXListAtBonePos", FXListAtBonePosFXNugget::parse, nullptr, 0},
1146+
{ "Decal", DecalFXNugget::parse, nullptr, 0},
10281147
{ nullptr, nullptr, nullptr, 0 }
10291148
};
10301149

Core/GameEngineDevice/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(GAMEENGINEDEVICE_SRC
2121
Include/W3DDevice/GameClient/Module/W3DPoliceCarDraw.h
2222
Include/W3DDevice/GameClient/Module/W3DProjectileStreamDraw.h
2323
Include/W3DDevice/GameClient/Module/W3DPropDraw.h
24+
Include/W3DDevice/GameClient/Module/W3DDecalDraw.h
2425
Include/W3DDevice/GameClient/Module/W3DRopeDraw.h
2526
Include/W3DDevice/GameClient/Module/W3DScienceModelDraw.h
2627
Include/W3DDevice/GameClient/Module/W3DSupplyDraw.h
@@ -110,6 +111,7 @@ set(GAMEENGINEDEVICE_SRC
110111
Source/W3DDevice/GameClient/Drawable/Draw/W3DPoliceCarDraw.cpp
111112
Source/W3DDevice/GameClient/Drawable/Draw/W3DProjectileStreamDraw.cpp
112113
Source/W3DDevice/GameClient/Drawable/Draw/W3DPropDraw.cpp
114+
Source/W3DDevice/GameClient/Drawable/Draw/W3DDecalDraw.cpp
113115
Source/W3DDevice/GameClient/Drawable/Draw/W3DRopeDraw.cpp
114116
Source/W3DDevice/GameClient/Drawable/Draw/W3DScienceModelDraw.cpp
115117
Source/W3DDevice/GameClient/Drawable/Draw/W3DSupplyDraw.cpp
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 Electronic Arts Inc.
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
////////////////////////////////////////////////////////////////////////////////
20+
// //
21+
// (c) 2001-2003 Electronic Arts Inc. //
22+
// //
23+
////////////////////////////////////////////////////////////////////////////////
24+
25+
// FILE: W3DDecalDraw.h //////////////////////////////////////////////////////////////////////////
26+
// Author: Andi W, May 26
27+
// Desc: Draw module for Decal FXNugget
28+
///////////////////////////////////////////////////////////////////////////////////////////////////
29+
30+
#pragma once
31+
32+
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
33+
#include "Common/DrawModule.h"
34+
#include "WW3D2/line3d.h"
35+
#include "W3DDevice/GameClient/W3DShadow.h"
36+
#include "WW3D2/boxrobj.h"
37+
38+
//-------------------------------------------------------------------------------------------------
39+
class W3DDecalDrawModuleData : public ModuleData
40+
{
41+
public:
42+
43+
AsciiString m_textureName;
44+
Real m_opacity; ///< value between 0 and 1
45+
UnsignedInt m_color; ///< color in ARGB format. (Alpha is ignored).
46+
// UnsignedInt m_lifetime;
47+
UnsignedInt m_fadeOutTime;
48+
UnsignedInt m_fadeInTime;
49+
ShadowType m_type; /// type of projection
50+
Real m_decalSizeX; /// 1/(world space extent of texture in x direction)
51+
Real m_decalSizeY; /// 1/(world space extent of texture in y direction)
52+
53+
W3DDecalDrawModuleData();
54+
~W3DDecalDrawModuleData();
55+
static void buildFieldParse(MultiIniFieldParse& p);
56+
// ugh, hack
57+
virtual const W3DDecalDrawModuleData* getAsW3DDecalDrawModuleData() const { return this; }
58+
};
59+
60+
//-------------------------------------------------------------------------------------------------
61+
/** W3D prop draw */
62+
//-------------------------------------------------------------------------------------------------
63+
class W3DDecalDraw : public DrawModule //, public DecalDrawInterface
64+
{
65+
66+
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( W3DDecalDraw, "W3DDecalDraw" )
67+
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( W3DDecalDraw, W3DDecalDrawModuleData )
68+
69+
public:
70+
71+
W3DDecalDraw( Thing *thing, const ModuleData* moduleData );
72+
// virtual destructor prototype provided by memory pool declaration
73+
74+
virtual void doDrawModule(const Matrix3D* transformMtx);
75+
virtual void setShadowsEnabled(Bool enable) { }
76+
virtual void releaseShadows(void) {}; ///< we don't care about preserving temporary shadows.
77+
virtual void allocateShadows(void) {}; ///< we don't care about preserving temporary shadows.
78+
virtual void setFullyObscuredByShroud(Bool fullyObscured);
79+
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
80+
virtual void reactToGeometryChange() { }
81+
82+
83+
//virtual DecalDrawInterface* getDecalDrawInterface() { return this; }
84+
//virtual const DecalDrawInterface* getDecalDrawInterface() const { return this; }
85+
86+
//virtual void initDecal(AsciiString texture, Real opacity, Int color, ShadowType type, UnsignedInt lifetime, UnsignedInt fadeOutTime, UnsignedInt fadeInTime, Real sizeX, Real sizeY);
87+
88+
89+
protected:
90+
//Bool m_propAdded;
91+
92+
OBBoxRenderObjClass* m_renderBox; // The render object
93+
Shadow* m_shadow; // the decal
94+
Bool m_fullyObscuredByShroud;
95+
UnsignedInt m_frameCreated;
96+
97+
private:
98+
void init_shadow();
99+
void init_renderBox(const Matrix3D* transformMtx);
100+
};

Core/GameEngineDevice/Include/W3DDevice/GameClient/Module/W3DModelDraw.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ struct ParticleSysBoneInfo
128128

129129
typedef std::vector<ParticleSysBoneInfo> ParticleSysBoneInfoVector;
130130

131+
//-------------------------------------------------------------------------------------------------
132+
struct FXEventInfo
133+
{
134+
AsciiString boneName;
135+
const FXList* fx;
136+
UnsignedInt frame;
137+
};
138+
139+
typedef std::vector<FXEventInfo> FXEventInfoVector;
140+
131141
//-------------------------------------------------------------------------------------------------
132142
struct PristineBoneInfo
133143
{
@@ -222,12 +232,18 @@ struct ModelConditionInfo
222232
Real m_animMinSpeedFactor; //Min speed factor (randomized each time it's played)
223233
Real m_animMaxSpeedFactor; //Max speed factor (randomized each time it's played)
224234

235+
FXEventInfoVector m_fxEvents; ///<frames, Bone names and attached FXLists
236+
225237
mutable PristineBoneInfoMap m_pristineBones;
226238
mutable TurretInfo m_turrets[MAX_TURRETS];
227239
mutable WeaponBarrelInfoVec m_weaponBarrelInfoVec[WEAPONSLOT_COUNT];
228240
mutable Bool m_hasRecoilBonesOrMuzzleFlashes[WEAPONSLOT_COUNT];
229241
mutable Byte m_validStuff;
230242

243+
// Animation Blending (needs WalkerDraw)
244+
UnsignedInt m_animBlendTime;
245+
246+
231247
enum
232248
{
233249
PRISTINE_BONES_VALID = 0x0001,
@@ -316,6 +332,8 @@ class W3DModelDrawModuleData : public ModuleData
316332

317333
Bool m_showForOwnerOnly; ///< show this model only to the owning player
318334

335+
Bool m_keepRecoilAcrossStates; ///< Don't reset recoil bones when switching states
336+
319337
// Bool m_disableMoveEffectsOverWater; ///< disable track marks and tread/wheel anims over water
320338

321339
W3DModelDrawModuleData();
@@ -434,6 +452,8 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
434452
RenderObjClass *getRenderObject() { return m_renderObject; }
435453
virtual Bool updateBonesForClientParticleSystems( void );///< this will reposition particle systems on the fly ML
436454

455+
virtual void handleFXEvents(); // Check frame times and trigger FX events at correct positions
456+
437457
virtual void onDrawableBoundToObject();
438458
virtual void setTerrainDecalSize(Real x, Real y);
439459
virtual void setTerrainDecalOpacity(Real o);
@@ -492,6 +512,16 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
492512
Int boneIndex;
493513
};
494514

515+
struct AnimInfoHelper
516+
{
517+
Int frameNum;
518+
Int mode;
519+
float numFrames;
520+
float fraction;
521+
};
522+
AnimInfoHelper m_prevAnimHelper;
523+
AnimInfoHelper getCurrentAnimHelper() const;
524+
495525

496526
typedef std::vector<WeaponRecoilInfo> WeaponRecoilInfoVec;
497527
typedef std::vector<ParticleSysTrackerType> ParticleSystemIDVec;
@@ -522,7 +552,7 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
522552
Real getCurrentAnimFraction() const;
523553
void applyCorrectModelStateAnimation();
524554
const ModelConditionInfo* findTransitionForSig(TransitionSig sig) const;
525-
void rebuildWeaponRecoilInfo(const ModelConditionInfo* state);
555+
void rebuildWeaponRecoilInfo(const ModelConditionInfo* state, bool clear = TRUE);
526556
void doHideShowProjectileObjects( UnsignedInt showCount, UnsignedInt maxCount, WeaponSlotType slot );///< Means effectively, show m of n.
527557
void nukeCurrentRender(Matrix3D* xform);
528558
void doStartOrStopParticleSys();

0 commit comments

Comments
 (0)