| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DProjectileStreamDraw.cpp ////////////////////////////////////////////////////////////
- // Tile a texture strung between Projectiles
- // Graham Smallwood, May 2002
- /////////////////////////////////////////////////////////////////////////////////////////////////
- #include "Common/Xfer.h"
- #include "GameClient/Drawable.h"
- #include "GameLogic/Object.h"
- #include "W3DDevice/GameClient/Module/W3DProjectileStreamDraw.h"
- #include "W3DDevice/GameClient/W3DDisplay.h"
- #include "W3DDevice/GameClient/W3DScene.h"
- #include "WW3D2/AssetMgr.h"
- #include "WW3D2/Segline.h"
- #include "WWMath/Vector3.h"
- //-------------------------------------------------------------------------------------------------
- W3DProjectileStreamDrawModuleData::W3DProjectileStreamDrawModuleData()
- {
- m_textureName = "";
- m_width = 0.0f;
- m_tileFactor = 0.0f;
- m_scrollRate = 0.0f;
- m_maxSegments = 0;
- }
- //-------------------------------------------------------------------------------------------------
- W3DProjectileStreamDrawModuleData::~W3DProjectileStreamDrawModuleData()
- {
- }
- //-------------------------------------------------------------------------------------------------
- void W3DProjectileStreamDrawModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- ModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "Texture", INI::parseAsciiString, NULL, offsetof(W3DProjectileStreamDrawModuleData, m_textureName) },
- { "Width", INI::parseReal, NULL, offsetof(W3DProjectileStreamDrawModuleData, m_width) },
- { "TileFactor", INI::parseReal, NULL, offsetof(W3DProjectileStreamDrawModuleData, m_tileFactor) },
- { "ScrollRate", INI::parseReal, NULL, offsetof(W3DProjectileStreamDrawModuleData, m_scrollRate) },
- { "MaxSegments", INI::parseInt, NULL, offsetof(W3DProjectileStreamDrawModuleData, m_maxSegments) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DProjectileStreamDraw::~W3DProjectileStreamDraw()
- {
- for( Int lineIndex = 0; lineIndex < m_linesValid; lineIndex++ )
- {
- SegmentedLineClass *deadLine = m_allLines[lineIndex];
- if (deadLine)
- { if (deadLine->Peek_Scene())
- W3DDisplay::m_3DScene->Remove_Render_Object( deadLine );
- REF_PTR_RELEASE( deadLine );
- }
- }
- REF_PTR_RELEASE( m_texture );
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DProjectileStreamDraw::W3DProjectileStreamDraw( Thing *thing, const ModuleData* moduleData ) : DrawModule( thing, moduleData )
- {
- const W3DProjectileStreamDrawModuleData* d = getW3DProjectileStreamDrawModuleData();
- m_texture = WW3DAssetManager::Get_Instance()->Get_Texture( d->m_textureName.str() );
- for( Int index = 0; index < MAX_PROJECTILE_STREAM; index++ )
- m_allLines[index] = NULL;
- m_linesValid = 0;
- }
- void W3DProjectileStreamDraw::setFullyObscuredByShroud(Bool fullyObscured)
- {
- if (fullyObscured)
- { //we need to remove all our lines from the scene because they are hidden
- for( Int lineIndex = 0; lineIndex < m_linesValid; lineIndex++ )
- {
- SegmentedLineClass *deadLine = m_allLines[lineIndex];
- if (deadLine && deadLine->Peek_Scene())
- deadLine->Remove();
- }
- }
- else
- { //we need to restore lines into scene
- for( Int lineIndex = 0; lineIndex < m_linesValid; lineIndex++ )
- {
- SegmentedLineClass *deadLine = m_allLines[lineIndex];
- if (deadLine && !deadLine->Peek_Scene())
- W3DDisplay::m_3DScene->Add_Render_Object(deadLine);
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Map behavior states into W3D animations. */
- //-------------------------------------------------------------------------------------------------
- void W3DProjectileStreamDraw::doDrawModule(const Matrix3D* )
- {
- // get object from logic
- Object *me = getDrawable()->getObject();
- if (me == NULL)
- return;
- static NameKeyType key_ProjectileStreamUpdate = NAMEKEY("ProjectileStreamUpdate");
- ProjectileStreamUpdate* update = (ProjectileStreamUpdate*)me->findUpdateModule(key_ProjectileStreamUpdate);
- const W3DProjectileStreamDrawModuleData *data = getW3DProjectileStreamDrawModuleData();
- Vector3 allPoints[MAX_PROJECTILE_STREAM];
- Int pointsUsed;
- update->getAllPoints( allPoints, &pointsUsed );
- Vector3 stagingPoints[MAX_PROJECTILE_STREAM];
- Vector3 zeroVector(0, 0, 0);
- Int linesMade = 0;
- Int currentMasterPoint = 0;
- UnsignedInt currentStagingPoint = 0;
- if( data->m_maxSegments )
- {
- // If I have a drawing cap, I need to increase the start point in the array. The furthest (oldest)
- // point from the tank is in spot zero.
- currentMasterPoint = pointsUsed - data->m_maxSegments;
- currentMasterPoint = max( 0, currentMasterPoint ); // (but if they say to draw more than exists, draw all)
- }
- // Okay. I have an array of ordered points that may have blanks in it. I need to copy to the staging area
- // until I hit a blank or the end. Then if I have a line made, I'll overwrite it, otherwise I'll make a new one.
- // I'll keep doing this until I run out of valid points.
- while( currentMasterPoint < pointsUsed )
- {
- while( currentMasterPoint < pointsUsed && allPoints[currentMasterPoint] != zeroVector )
- {
- // While I am not looking at a bad point (off edge or zero)
- stagingPoints[currentStagingPoint] = allPoints[currentMasterPoint];// copy to the staging
- currentStagingPoint++;// increment how many I have
- currentMasterPoint++;// increment what I am looking at
- }
- // Use or reuse a line
- if( currentStagingPoint > 1 )
- {
- // Don't waste a line on a double hole (0) or a one point line (1)
- makeOrUpdateLine( stagingPoints, currentStagingPoint, linesMade );
- linesMade++;// keep track of how many are real this frame
- }
- currentMasterPoint++;//I am either pointed off the edge anyway, or I am pointed at a zero I want to skip
- currentStagingPoint = 0;//start over in the staging area
- }
- Int oldLinesValid = m_linesValid;
- for( Int lineIndex = linesMade; lineIndex < oldLinesValid; lineIndex++ )
- {
- // Delete any line we aren't using anymore.
- SegmentedLineClass *deadLine = m_allLines[lineIndex];
- if (deadLine->Peek_Scene())
- W3DDisplay::m_3DScene->Remove_Render_Object( deadLine );
- REF_PTR_RELEASE( deadLine );
- m_allLines[lineIndex] = NULL;
- m_linesValid--;
- }
- }
- void W3DProjectileStreamDraw::makeOrUpdateLine( Vector3 *points, UnsignedInt pointCount, Int lineIndex )
- {
- Bool newLine = FALSE;
- if( m_allLines[lineIndex] == NULL )
- {
- //Need a new one if this is blank, otherwise I'll reset the existing one
- m_allLines[lineIndex] = NEW SegmentedLineClass;
- m_linesValid++;
- newLine = TRUE;
- }
- SegmentedLineClass *line = m_allLines[lineIndex];
- line->Set_Points(pointCount, points); //tell the line which points to use
- if( newLine )
- {
- // This is one time stuff we only need to do if this is a new and not a change
- const W3DProjectileStreamDrawModuleData *data = getW3DProjectileStreamDrawModuleData();
- line->Set_Texture(m_texture); //set the texture
- line->Set_Shader(ShaderClass::_PresetAdditiveSpriteShader); //pick the alpha blending mode you want - see shader.h for others.
- line->Set_Width(data->m_width); //set line width in world units
- line->Set_Texture_Mapping_Mode(SegLineRendererClass::TILED_TEXTURE_MAP); //this tiles the texture across the line
- line->Set_Texture_Tile_Factor(data->m_tileFactor); //number of times to tile texture across each segment
- line->Set_UV_Offset_Rate(Vector2(0.0f,data->m_scrollRate)); //amount to scroll texture on each draw
- W3DDisplay::m_3DScene->Add_Render_Object( line); //add it to our scene so it gets rendered with other objects.
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void W3DProjectileStreamDraw::crc( Xfer *xfer )
- {
- // extend base class
- DrawModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void W3DProjectileStreamDraw::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- DrawModule::xfer( xfer );
- // Graham says there is no data that needs saving here
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void W3DProjectileStreamDraw::loadPostProcess( void )
- {
- // extend base class
- DrawModule::loadPostProcess();
- } // end loadPostProcess
|