Initial commit

This commit is contained in:
Brian Harris
2012-11-26 12:58:24 -06:00
parent a5214f79ef
commit 5016f605b8
1115 changed files with 587266 additions and 0 deletions

405
neo/swf/SWF.h Normal file
View File

@@ -0,0 +1,405 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_H__
#define __SWF_H__
#include "SWF_Enums.h"
#include "SWF_Types.h"
#include "SWF_Bitstream.h"
#include "SWF_ScriptVar.h"
#include "SWF_Sprites.h"
#include "SWF_ScriptObject.h"
#include "SWF_ParmList.h"
#include "SWF_ScriptFunction.h"
#include "SWF_SpriteInstance.h"
#include "SWF_ShapeParser.h"
#include "SWF_TextInstance.h"
class idSWFDictionaryEntry {
public:
idSWFDictionaryEntry();
~idSWFDictionaryEntry();
idSWFDictionaryEntry & operator=( idSWFDictionaryEntry & other );
swfDictType_t type;
const idMaterial * material;
idSWFShape * shape;
idSWFSprite * sprite;
idSWFFont * font;
idSWFText * text;
idSWFEditText * edittext;
idVec2i imageSize;
idVec2i imageAtlasOffset;
// the compressed images are normalize to reduce compression artifacts,
// color must be scaled down by this
idVec4 channelScale;
};
struct purgableSwfImage_t {
purgableSwfImage_t() { image = NULL; swfFrameNum = 0; }
idImage * image;
unsigned swfFrameNum;
};
/*
================================================
This class handles loading and rendering SWF files
================================================
*/
class idSWF {
public:
idSWF( const char * filename, idSoundWorld * soundWorld = NULL );
~idSWF();
bool IsLoaded() { return ( frameRate > 0 ); }
bool IsActive() { return isActive; }
void Activate( bool b );
const char * GetName() { return filename; }
void Pause() { mainspriteInstance->Stop(); paused = true; }
void Resume() { mainspriteInstance->Play(); paused = false; }
bool IsPaused() { return paused; }
void SetPausedRender( bool valid ) { pausedRender = valid; }
bool GetPausedRender() { return pausedRender; }
void Render( idRenderSystem * gui, int time = 0, bool isSplitscreen = false );
bool HandleEvent( const sysEvent_t * event );
bool InhibitControl();
void ForceInhibitControl( bool val ) { inhibitControl = val; }
void SetGlobal( const char * name, const idSWFScriptVar & value ) { globals->Set( name, value ); }
void SetGlobalNative( const char * name, idSWFScriptNativeVariable * native ) { globals->SetNative( name, native ); }
idSWFScriptVar GetGlobal( const char * name ) { return globals->Get( name ); }
idSWFScriptObject & GetRootObject() { assert( mainspriteInstance->GetScriptObject() != NULL ); return *( mainspriteInstance->GetScriptObject() ); }
void Invoke( const char * functionName, const idSWFParmList & parms );
void Invoke( const char * functionName, const idSWFParmList & parms, idSWFScriptVar & scriptVar );
void Invoke( const char * functionName, const idSWFParmList & parms, bool & functionExists );
int PlaySound( const char * sound, int channel = SCHANNEL_ANY, bool blocking = false );
void StopSound( int channel = SCHANNEL_ANY );
float GetFrameWidth() const { return frameWidth; }
float GetFrameHeight() const { return frameHeight; }
int GetMouseX() { return mouseX; }
int GetMouseY() { return mouseY; }
bool UseCircleForAccept();
void SetSWFScale( float scale ) { swfScale = scale; }
void SetForceNonPCGetPlatform() { forceNonPCPlatform = true; }
idRandom2 & GetRandom() { return random; }
int GetPlatform();
//----------------------------------
// SWF_Dictionary.cpp
//----------------------------------
idSWFDictionaryEntry * AddDictionaryEntry( int characterID, swfDictType_t type );
idSWFDictionaryEntry * FindDictionaryEntry( int characterID, swfDictType_t type );
idSWFDictionaryEntry * FindDictionaryEntry( int characterID );
idSWFDictionaryEntry * GetDictionaryEntry( int index ) { return &dictionary[ index ]; }
int GetNumDictionaryEntry() { return dictionary.Num(); }
idSWFScriptObject * HitTest( idSWFSpriteInstance * spriteInstance, const swfRenderState_t & renderState, int x, int y, idSWFScriptObject * parentObject );
private:
idStr filename;
ID_TIME_T timestamp;
float frameWidth;
float frameHeight;
uint16 frameRate;
float renderBorder;
float swfScale;
idVec2 scaleToVirtual;
int lastRenderTime;
bool isActive;
bool inhibitControl;
bool useInhibtControl;
// certain screens need to be rendered when the pause menu is up so if this flag is
// set on the gui we will allow it to render at a paused state;
bool pausedRender;
bool mouseEnabled;
bool useMouse;
bool blackbars;
bool crop;
bool paused;
bool hasHitObject;
bool forceNonPCPlatform;
idRandom2 random;
static int mouseX; // mouse x coord for all flash files
static int mouseY; // mouse y coord for all flash files
static bool isMouseInClientArea;
idSWFScriptObject * mouseObject;
idSWFScriptObject * hoverObject;
idSWFSprite * mainsprite;
idSWFSpriteInstance * mainspriteInstance;
idSWFScriptObject * globals;
idSWFScriptObject * shortcutKeys;
idSoundWorld * soundWorld;
const idMaterial * atlasMaterial;
idBlockAlloc< idSWFSpriteInstance, 16 > spriteInstanceAllocator;
idBlockAlloc< idSWFTextInstance, 16 > textInstanceAllocator;
#define SWF_NATIVE_FUNCTION_SWF_DECLARE( x ) \
class idSWFScriptFunction_##x : public idSWFScriptFunction_Nested< idSWF > { \
public: \
idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ); \
} scriptFunction_##x;
SWF_NATIVE_FUNCTION_SWF_DECLARE( shortcutKeys_clear );
SWF_NATIVE_FUNCTION_SWF_DECLARE( deactivate );
SWF_NATIVE_FUNCTION_SWF_DECLARE( inhibitControl );
SWF_NATIVE_FUNCTION_SWF_DECLARE( useInhibit );
SWF_NATIVE_FUNCTION_SWF_DECLARE( precacheSound );
SWF_NATIVE_FUNCTION_SWF_DECLARE( playSound );
SWF_NATIVE_FUNCTION_SWF_DECLARE( stopSounds );
SWF_NATIVE_FUNCTION_SWF_DECLARE( getPlatform );
SWF_NATIVE_FUNCTION_SWF_DECLARE( getTruePlatform );
SWF_NATIVE_FUNCTION_SWF_DECLARE( getLocalString );
SWF_NATIVE_FUNCTION_SWF_DECLARE( swapPS3Buttons );
SWF_NATIVE_FUNCTION_SWF_DECLARE( getCVarInteger );
SWF_NATIVE_FUNCTION_SWF_DECLARE( setCVarInteger );
SWF_NATIVE_FUNCTION_SWF_DECLARE( strReplace );
SWF_NATIVE_FUNCTION_SWF_DECLARE( acos );
SWF_NATIVE_FUNCTION_SWF_DECLARE( cos );
SWF_NATIVE_FUNCTION_SWF_DECLARE( sin );
SWF_NATIVE_FUNCTION_SWF_DECLARE( round );
SWF_NATIVE_FUNCTION_SWF_DECLARE( pow );
SWF_NATIVE_FUNCTION_SWF_DECLARE( sqrt );
SWF_NATIVE_FUNCTION_SWF_DECLARE( abs );
SWF_NATIVE_FUNCTION_SWF_DECLARE( rand );
SWF_NATIVE_FUNCTION_SWF_DECLARE( floor );
SWF_NATIVE_FUNCTION_SWF_DECLARE( ceil );
SWF_NATIVE_FUNCTION_SWF_DECLARE( toUpper );
SWF_NATIVE_VAR_DECLARE_NESTED_READONLY( platform, idSWFScriptFunction_getPlatform, Call( object, idSWFParmList() ) );
SWF_NATIVE_VAR_DECLARE_NESTED( blackbars, idSWF );
SWF_NATIVE_VAR_DECLARE_NESTED( crop, idSWF );
class idSWFScriptFunction_Object : public idSWFScriptFunction {
public:
idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) { return idSWFScriptVar(); }
void AddRef() { }
void Release() { }
idSWFScriptObject * GetPrototype() { return &object; }
void SetPrototype( idSWFScriptObject * _object ) { assert( false ); }
idSWFScriptObject object;
} scriptFunction_Object;
idList< idSWFDictionaryEntry, TAG_SWF > dictionary;
struct keyButtonImages_t {
keyButtonImages_t() {
key = "";
xbImage = "";
psImage = "";
width = 0;
height = 0;
baseline = 0;
}
keyButtonImages_t( const char* _key, const char* _xbImage, const char* _psImage, int w, int h, int _baseline ) {
key = _key;
xbImage = _xbImage;
psImage = _psImage;
width = w;
height = h;
baseline = _baseline;
}
const char * key;
const char * xbImage;
const char * psImage;
int width;
int height;
int baseline;
};
idList< keyButtonImages_t, TAG_SWF > tooltipButtonImage;
struct tooltipIcon_t {
tooltipIcon_t() {
startIndex = -1;
endIndex = -1;
material = NULL;
imageWidth = 0;
imageHeight = 0;
baseline = 0;
};
int startIndex;
int endIndex;
const idMaterial * material;
short imageWidth;
short imageHeight;
int baseline;
};
idList< tooltipIcon_t, TAG_SWF > tooltipIconList;
const idMaterial * guiSolid;
const idMaterial * guiCursor_arrow;
const idMaterial * guiCursor_hand;
const idMaterial * white;
private:
friend class idSWFSprite;
friend class idSWFSpriteInstance;
bool LoadSWF( const char * fullpath );
bool LoadBinary( const char * bfilename, ID_TIME_T sourceTime );
void WriteBinary( const char * bfilename );
//----------------------------------
// SWF_Shapes.cpp
//----------------------------------
void DefineShape( idSWFBitStream & bitstream );
void DefineShape2( idSWFBitStream & bitstream );
void DefineShape3( idSWFBitStream & bitstream );
void DefineShape4( idSWFBitStream & bitstream );
void DefineMorphShape( idSWFBitStream & bitstream );
//----------------------------------
// SWF_Sprites.cpp
//----------------------------------
void DefineSprite( idSWFBitStream & bitstream );
//----------------------------------
// SWF_Sounds.cpp
//----------------------------------
void DefineSound( idSWFBitStream & bitstream );
//----------------------------------
// SWF_Render.cpp
//----------------------------------
void DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *material );
void DrawStretchPic( const idVec4 & topLeft, const idVec4 & topRight, const idVec4 & bottomRight, const idVec4 & bottomLeft, const idMaterial * material );
void RenderSprite( idRenderSystem * gui, idSWFSpriteInstance * sprite, const swfRenderState_t & renderState, int time, bool isSplitscreen = false );
void RenderMask( idRenderSystem * gui, const swfDisplayEntry_t * mask, const swfRenderState_t & renderState, const int stencilMode );
void RenderShape( idRenderSystem * gui, const idSWFShape * shape, const swfRenderState_t & renderState );
void RenderMorphShape( idRenderSystem * gui, const idSWFShape* shape, const swfRenderState_t & renderState );
void DrawEditCursor( idRenderSystem * gui, float x, float y, float w, float h, const swfMatrix_t & matrix );
void DrawLine( idRenderSystem * gui, const idVec2 & p1, const idVec2 & p2, float width, const swfMatrix_t & matrix );
void RenderEditText( idRenderSystem * gui, idSWFTextInstance * textInstance, const swfRenderState_t & renderState, int time, bool isSplitscreen = false );
uint64 GLStateForRenderState( const swfRenderState_t & renderState );
void FindTooltipIcons( idStr * text );
//----------------------------------
// SWF_Image.cpp
//----------------------------------
class idDecompressJPEG {
public:
idDecompressJPEG();
~idDecompressJPEG();
byte * Load( const byte * input, int inputSize, int & width, int & height );
private:
void * vinfo;
};
idDecompressJPEG jpeg;
void LoadImage( int characterID, const byte * imageData, int width, int height );
void JPEGTables( idSWFBitStream & bitstream );
void DefineBits( idSWFBitStream & bitstream );
void DefineBitsJPEG2( idSWFBitStream & bitstream );
void DefineBitsJPEG3( idSWFBitStream & bitstream );
void DefineBitsLossless( idSWFBitStream & bitstream );
void DefineBitsLossless2( idSWFBitStream & bitstream );
// per-swf image atlas
struct imageToPack_t {
int characterID;
idVec2i trueSize; // in texels
byte * imageData; // trueSize.x * trueSize.y * 4
idVec2i allocSize; // in DXT tiles, includes a border texel and rounding up to DXT blocks
};
class idSortBlocks : public idSort_Quick< imageToPack_t, idSortBlocks > {
public:
int Compare( const imageToPack_t & a, const imageToPack_t & b ) const {
return ( b.allocSize.x * b.allocSize.y ) - ( a.allocSize.x * a.allocSize.y );
}
};
idList<imageToPack_t, TAG_SWF> packImages; // only used during creation
void WriteSwfImageAtlas( const char *filename );
//----------------------------------
// SWF_Text.cpp
//----------------------------------
void DefineFont2( idSWFBitStream & bitstream );
void DefineFont3( idSWFBitStream & bitstream );
void DefineTextX( idSWFBitStream & bitstream, bool rgba );
void DefineText( idSWFBitStream & bitstream );
void DefineText2( idSWFBitStream & bitstream );
void DefineEditText( idSWFBitStream & bitstream );
//----------------------------------
// SWF_Zlib.cpp
//----------------------------------
bool Inflate( const byte * input, int inputSize, byte * output, int outputSize );
public:
//----------------------------------
// SWF_Names.cpp
//----------------------------------
static const char * GetTagName( swfTag_t tag );
static const char * GetActionName( swfAction_t action );
};
#endif // !__SWF_H__

402
neo/swf/SWF_Bitstream.cpp Normal file
View File

@@ -0,0 +1,402 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#define NBM( x ) (int32)( ( 1LL << x ) - 1 )
int maskForNumBits[33] = { NBM( 0x00 ), NBM( 0x01 ), NBM( 0x02 ), NBM( 0x03 ),
NBM( 0x04 ), NBM( 0x05 ), NBM( 0x06 ), NBM( 0x07 ),
NBM( 0x08 ), NBM( 0x09 ), NBM( 0x0A ), NBM( 0x0B ),
NBM( 0x0C ), NBM( 0x0D ), NBM( 0x0E ), NBM( 0x0F ),
NBM( 0x10 ), NBM( 0x11 ), NBM( 0x12 ), NBM( 0x13 ),
NBM( 0x14 ), NBM( 0x15 ), NBM( 0x16 ), NBM( 0x17 ),
NBM( 0x18 ), NBM( 0x19 ), NBM( 0x1A ), NBM( 0x1B ),
NBM( 0x1C ), NBM( 0x1D ), NBM( 0x1E ), NBM( 0x1F ), -1 };
#define NBS( x ) (int32)( (-1) << ( x - 1 ) )
int signForNumBits[33] = { NBS( 0x01 ), NBS( 0x01 ), NBS( 0x02 ), NBS( 0x03 ),
NBS( 0x04 ), NBS( 0x05 ), NBS( 0x06 ), NBS( 0x07 ),
NBS( 0x08 ), NBS( 0x09 ), NBS( 0x0A ), NBS( 0x0B ),
NBS( 0x0C ), NBS( 0x0D ), NBS( 0x0E ), NBS( 0x0F ),
NBS( 0x10 ), NBS( 0x11 ), NBS( 0x12 ), NBS( 0x13 ),
NBS( 0x14 ), NBS( 0x15 ), NBS( 0x16 ), NBS( 0x17 ),
NBS( 0x18 ), NBS( 0x19 ), NBS( 0x1A ), NBS( 0x1B ),
NBS( 0x1C ), NBS( 0x1D ), NBS( 0x1E ), NBS( 0x1F ), NBS( 0x20 ) };
#define ID_FORCEINLINE __forceinline
/*
========================
idSWFBitStream::idSWFBitStream
========================
*/
idSWFBitStream::idSWFBitStream() {
free = false;
Free();
}
/*
========================
idSWFBitStream::operator=
========================
*/
idSWFBitStream & idSWFBitStream::operator=( idSWFBitStream & other ) {
Free();
free = other.free;
startp = other.startp;
readp = other.readp;
endp = other.endp;
currentBit = other.currentBit;
currentByte = other.currentByte;
if ( other.free ) {
// this is actually quite dangerous, but we need to do this
// because these things are copied around inside idList
other.free = false;
}
return *this;
}
/*
========================
idSWFBitStream::Free
========================
*/
void idSWFBitStream::Free() {
if ( free ) {
Mem_Free( (void *)startp );
}
free = false;
startp = NULL;
endp = NULL;
readp = NULL;
ResetBits();
}
/*
========================
idSWFBitStream::Load
========================
*/
void idSWFBitStream::Load( const byte * data, uint32 len, bool copy ) {
Free();
if ( copy ) {
free = true;
startp = (const byte *)Mem_Alloc( len, TAG_SWF );
memcpy( (byte *)startp, data, len );
} else {
free = false;
startp = data;
}
endp = startp + len;
readp = startp;
ResetBits();
}
/*
========================
idSWFBitStream::ReadEncodedU32
========================
*/
uint32 idSWFBitStream::ReadEncodedU32() {
uint32 result = 0;
for ( int i = 0; i < 5; i++ ) {
byte b = ReadU8();
result |= ( b & 0x7F ) << ( 7 * i );
if ( ( b & 0x80 ) == 0 ) {
return result;
}
}
return result;
}
/*
========================
idSWFBitStream::ReadData
========================
*/
const byte * idSWFBitStream::ReadData( int size ) {
assert( readp >= startp && readp <= endp );
ResetBits();
if ( readp + size > endp ) {
// buffer overrun
assert( false );
readp = endp;
return startp;
}
const byte * buffer = readp;
readp += size;
assert( readp >= startp && readp <= endp );
return buffer;
}
/*
========================
idSWFBitStream::ReadInternalU
========================
*/
ID_FORCEINLINE unsigned int idSWFBitStream::ReadInternalU( uint64 & regCurrentBit, uint64 & regCurrentByte, unsigned int numBits ) {
assert( numBits <= 32 );
// read bits with only one microcoded shift instruction (shift with variable) on the consoles
// this routine never reads more than 7 bits beyond the requested number of bits from the stream
// such that calling ResetBits() never discards more than 7 bits and aligns with the next byte
uint64 numExtraBytes = ( numBits - regCurrentBit + 7 ) >> 3;
regCurrentBit = regCurrentBit + ( numExtraBytes << 3 ) - numBits;
for ( int i = 0; i < numExtraBytes; i++ ) {
regCurrentByte = ( regCurrentByte << 8 ) | readp[i];
}
readp += numExtraBytes;
return (unsigned int) ( ( regCurrentByte >> regCurrentBit ) & maskForNumBits[numBits] );
}
/*
========================
idSWFBitStream::ReadInternalS
========================
*/
ID_FORCEINLINE int idSWFBitStream::ReadInternalS( uint64 & regCurrentBit, uint64 & regCurrentByte, unsigned int numBits ) {
int i = (int)ReadInternalU( regCurrentBit, regCurrentByte, numBits );
// sign extend without microcoded shift instrunction (shift with variable) on the consoles
int s = signForNumBits[numBits];
return ( ( i + s ) ^ s );
}
/*
========================
idSWFBitStream::ReadU
========================
*/
unsigned int idSWFBitStream::ReadU( unsigned int numBits ) {
return ReadInternalU( currentBit, currentByte, numBits );
}
/*
========================
idSWFBitStream::ReadS
========================
*/
int idSWFBitStream::ReadS( unsigned int numBits ) {
return ReadInternalS( currentBit, currentByte, numBits );
}
/*
========================
idSWFBitStream::ReadRect
========================
*/
void idSWFBitStream::ReadRect( swfRect_t & rect ) {
uint64 regCurrentBit = 0;
uint64 regCurrentByte = 0;
int nBits = ReadInternalU( regCurrentBit, regCurrentByte, 5 );
int tl_x = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
int br_x = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
int tl_y = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
int br_y = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
rect.tl.x = SWFTWIP( tl_x );
rect.br.x = SWFTWIP( br_x );
rect.tl.y = SWFTWIP( tl_y );
rect.br.y = SWFTWIP( br_y );
currentBit = regCurrentBit;
currentByte = regCurrentByte;
}
/*
========================
idSWFBitStream::ReadMatrix
========================
*/
void idSWFBitStream::ReadMatrix( swfMatrix_t & matrix ) {
uint64 regCurrentBit = 0;
uint64 regCurrentByte = 0;
unsigned int hasScale = ReadInternalU( regCurrentBit, regCurrentByte, 1 );
int xx;
int yy;
if ( !hasScale ) {
xx = 65536;
yy = 65536;
} else {
int nBits = ReadInternalU( regCurrentBit, regCurrentByte, 5 );
xx = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
yy = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
}
unsigned int hasRotate = ReadInternalU( regCurrentBit, regCurrentByte, 1 );
int yx;
int xy;
if ( !hasRotate ) {
yx = 0;
xy = 0;
} else {
int nBits = ReadInternalU( regCurrentBit, regCurrentByte, 5 );
yx = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
xy = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
}
int nBits = ReadInternalU( regCurrentBit, regCurrentByte, 5 );
int tx = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
int ty = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
currentBit = regCurrentBit;
currentByte = regCurrentByte;
matrix.xx = SWFFIXED16( xx );
matrix.yy = SWFFIXED16( yy );
matrix.yx = SWFFIXED16( yx );
matrix.xy = SWFFIXED16( xy );
matrix.tx = SWFTWIP( tx );
matrix.ty = SWFTWIP( ty );
}
/*
========================
idSWFBitStream::ReadColorXFormRGBA
========================
*/
void idSWFBitStream::ReadColorXFormRGBA( swfColorXform_t & cxf ) {
uint64 regCurrentBit = 0;
uint64 regCurrentByte = 0;
unsigned int hasAddTerms = ReadInternalU( regCurrentBit, regCurrentByte, 1 );
unsigned int hasMulTerms = ReadInternalU( regCurrentBit, regCurrentByte, 1 );
int nBits = ReadInternalU( regCurrentBit, regCurrentByte, 4 );
union { int i[4]; } m;
union { int i[4]; } a;
if ( !hasMulTerms ) {
m.i[0] = 256;
m.i[1] = 256;
m.i[2] = 256;
m.i[3] = 256;
} else {
m.i[0] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
m.i[1] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
m.i[2] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
m.i[3] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
}
if ( !hasAddTerms ) {
a.i[0] = 0;
a.i[1] = 0;
a.i[2] = 0;
a.i[3] = 0;
} else {
a.i[0] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
a.i[1] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
a.i[2] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
a.i[3] = ReadInternalS( regCurrentBit, regCurrentByte, nBits );
}
currentBit = regCurrentBit;
currentByte = regCurrentByte;
for ( int i = 0; i < 4; i++ ) {
cxf.mul[i] = SWFFIXED8( m.i[i] );
cxf.add[i] = SWFFIXED8( a.i[i] );
}
}
/*
========================
idSWFBitStream::ReadString
========================
*/
const char * idSWFBitStream::ReadString() {
return (const char *)ReadData( idStr::Length( (const char *)readp ) + 1 );
}
/*
========================
idSWFBitStream::ReadColorRGB
========================
*/
void idSWFBitStream::ReadColorRGB( swfColorRGB_t & color ) {
ResetBits();
color.r = *readp++;
color.g = *readp++;
color.b = *readp++;
}
/*
========================
idSWFBitStream::ReadColorRGBA
========================
*/
void idSWFBitStream::ReadColorRGBA( swfColorRGBA_t & color ) {
ResetBits();
color.r = *readp++;
color.g = *readp++;
color.b = *readp++;
color.a = *readp++;
}
/*
========================
idSWFBitStream::ReadGradient
========================
*/
void idSWFBitStream::ReadGradient( swfGradient_t & grad, bool rgba ) {
grad.numGradients = ReadU8() & 0xF; // the top 4 bits control spread and interpolation mode, but we ignore them
for ( int i = 0; i < grad.numGradients; i++ ) {
grad.gradientRecords[i].startRatio = ReadU8();
if ( rgba ) {
ReadColorRGBA( grad.gradientRecords[i].startColor );
} else {
ReadColorRGB( grad.gradientRecords[i].startColor );
}
grad.gradientRecords[i].endRatio = grad.gradientRecords[i].startRatio;
grad.gradientRecords[i].endColor = grad.gradientRecords[i].startColor;
}
}
/*
========================
idSWFBitStream::ReadMorphGradient
========================
*/
void idSWFBitStream::ReadMorphGradient( swfGradient_t & grad ) {
grad.numGradients = ReadU8() & 0xF; // the top 4 bits control spread and interpolation mode, but we ignore them
for ( int i = 0; i < grad.numGradients; i++ ) {
grad.gradientRecords[i].startRatio = ReadU8();
ReadColorRGBA( grad.gradientRecords[i].startColor );
grad.gradientRecords[i].endRatio = ReadU8();
ReadColorRGBA( grad.gradientRecords[i].endColor );
}
}

145
neo/swf/SWF_Bitstream.h Normal file
View File

@@ -0,0 +1,145 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_BITSTREAM_H__
#define __SWF_BITSTREAM_H__
class idSWFBitStream {
public:
idSWFBitStream();
idSWFBitStream( const byte * data, uint32 len, bool copy ) { free = false; Load( data, len, copy ); }
~idSWFBitStream() { Free(); }
idSWFBitStream & operator=( idSWFBitStream & other );
void Load( const byte * data, uint32 len, bool copy );
void Free();
const byte * Ptr() { return startp; }
uint32 Length() const { return (uint32)( endp - startp ); }
uint32 Tell() const { return (uint32)( readp - startp ); }
void Seek( int32 offset ) { readp += offset; }
void Rewind() { readp = startp; }
void ResetBits();
int ReadS( unsigned int numBits );
unsigned int ReadU( unsigned int numBits );
bool ReadBool();
const byte * ReadData( int size );
template< typename T >
void ReadLittle( T & val );
uint8 ReadU8();
uint16 ReadU16();
uint32 ReadU32();
int16 ReadS16();
int32 ReadS32();
uint32 ReadEncodedU32();
float ReadFixed8();
float ReadFixed16();
float ReadFloat();
double ReadDouble();
const char * ReadString();
void ReadRect( swfRect_t & rect );
void ReadMatrix( swfMatrix_t & matrix );
void ReadColorXFormRGBA( swfColorXform_t & cxf );
void ReadColorRGB( swfColorRGB_t & color );
void ReadColorRGBA( swfColorRGBA_t & color );
void ReadGradient( swfGradient_t & grad, bool rgba );
void ReadMorphGradient( swfGradient_t & grad );
private:
bool free;
const byte * startp;
const byte * endp;
const byte * readp;
uint64 currentBit;
uint64 currentByte;
int ReadInternalS( uint64 & regCurrentBit, uint64 & regCurrentByte, unsigned int numBits );
unsigned int ReadInternalU( uint64 & regCurrentBit, uint64 & regCurrentByte, unsigned int numBits );
};
/*
========================
idSWFBitStream::ResetBits
========================
*/
ID_INLINE void idSWFBitStream::ResetBits() {
currentBit = 0;
currentByte = 0;
}
/*
========================
idSWFBitStream::ReadLittle
========================
*/
template< typename T >
void idSWFBitStream::ReadLittle( T & val ) {
val = *(T *)ReadData( sizeof( val ) );
idSwap::Little( val );
}
/*
========================
Wrappers for the most basic types
========================
*/
ID_INLINE bool idSWFBitStream::ReadBool() { return ( ReadU( 1 ) != 0 ); }
ID_INLINE uint8 idSWFBitStream::ReadU8() { ResetBits(); return *readp++; }
ID_INLINE uint16 idSWFBitStream::ReadU16() { ResetBits(); readp += 2; return ( readp[-2] | ( readp[-1] << 8 ) ); }
ID_INLINE uint32 idSWFBitStream::ReadU32() { ResetBits(); readp += 4; return ( readp[-4] | ( readp[-3] << 8 ) | ( readp[-2] << 16 ) | ( readp[-1] << 24 ) ); }
ID_INLINE int16 idSWFBitStream::ReadS16() { ResetBits(); readp += 2; return ( readp[-2] | ( readp[-1] << 8 ) ); }
ID_INLINE int32 idSWFBitStream::ReadS32() { ResetBits(); readp += 4; return ( readp[-4] | ( readp[-3] << 8 ) | ( readp[-2] << 16 ) | ( readp[-1] << 24 ) ); }
ID_INLINE float idSWFBitStream::ReadFixed8() { ResetBits(); readp += 2; return SWFFIXED8( ( readp[-2] | ( readp[-1] << 8 ) ) ); }
ID_INLINE float idSWFBitStream::ReadFixed16() { ResetBits(); readp += 4; return SWFFIXED16( ( readp[-4] | ( readp[-3] << 8 ) | ( readp[-2] << 16 ) | ( readp[-1] << 24 ) ) ); }
ID_INLINE float idSWFBitStream::ReadFloat() { ResetBits(); readp += 4; uint32 i = ( readp[-4] | ( readp[-3] << 8 ) | ( readp[-2] << 16 ) | ( readp[-1] << 24 ) ); return (float &)i; }
ID_INLINE double idSWFBitStream::ReadDouble() {
const byte * swfIsRetarded = ReadData( 8 );
byte buffer[8];
buffer[0] = swfIsRetarded[4];
buffer[1] = swfIsRetarded[5];
buffer[2] = swfIsRetarded[6];
buffer[3] = swfIsRetarded[7];
buffer[4] = swfIsRetarded[0];
buffer[5] = swfIsRetarded[1];
buffer[6] = swfIsRetarded[2];
buffer[7] = swfIsRetarded[3];
double d = *(double *)buffer;
idSwap::Little( d );
return d;
}
#endif // !__SWF_BITSTREAM_H__

155
neo/swf/SWF_Dictionary.cpp Normal file
View File

@@ -0,0 +1,155 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
========================
idSWF::idSWFDictionaryEntry::idSWFDictionaryEntry
========================
*/
idSWFDictionaryEntry::idSWFDictionaryEntry() :
type( SWF_DICT_NULL ),
material( NULL ),
shape( NULL ),
sprite( NULL ),
font( NULL ),
text( NULL ),
edittext( NULL ),
imageSize( 0, 0 ),
imageAtlasOffset( 0, 0 ),
channelScale( 1.0f, 1.0f, 1.0f, 1.0f ) {
}
/*
========================
idSWF::idSWFDictionaryEntry::idSWFDictionaryEntry
========================
*/
idSWFDictionaryEntry::~idSWFDictionaryEntry() {
delete shape;
delete sprite;
delete font;
delete text;
delete edittext;
}
/*
========================
idSWF::idSWFDictionaryEntry::operator=
This exists mostly so idList works right
========================
*/
idSWFDictionaryEntry & idSWFDictionaryEntry::operator=( idSWFDictionaryEntry & other ) {
type = other.type;
material = other.material;
shape = other.shape;
sprite = other.sprite;
font = other.font;
text = other.text;
edittext = other.edittext;
imageSize = other.imageSize;
imageAtlasOffset = other.imageAtlasOffset;
other.type = SWF_DICT_NULL;
other.material = NULL;
other.shape = NULL;
other.sprite = NULL;
other.font = NULL;
other.text = NULL;
other.edittext = NULL;
return *this;
}
/*
========================
idSWF::AddDictionaryEntry
========================
*/
idSWFDictionaryEntry * idSWF::AddDictionaryEntry( int characterID, swfDictType_t type ) {
if ( dictionary.Num() < characterID + 1 ) {
dictionary.SetNum( characterID + 1 );
}
if ( dictionary[ characterID ].type != SWF_DICT_NULL ) {
idLib::Warning( "%s: Duplicate character %d", filename.c_str(), characterID );
return NULL;
}
dictionary[ characterID ].type = type;
if ( ( type == SWF_DICT_SHAPE ) || ( type == SWF_DICT_MORPH ) ) {
dictionary[ characterID ].shape = new (TAG_SWF) idSWFShape;
} else if ( type == SWF_DICT_SPRITE ) {
dictionary[ characterID ].sprite = new (TAG_SWF) idSWFSprite( this );
} else if ( type == SWF_DICT_FONT ) {
dictionary[ characterID ].font = new (TAG_SWF) idSWFFont;
} else if ( type == SWF_DICT_TEXT ) {
dictionary[ characterID ].text = new (TAG_SWF) idSWFText;
} else if ( type == SWF_DICT_EDITTEXT ) {
dictionary[ characterID ].edittext = new (TAG_SWF) idSWFEditText;
}
return &dictionary[ characterID ];
}
/*
========================
FindDictionaryEntry
========================
*/
idSWFDictionaryEntry * idSWF::FindDictionaryEntry( int characterID, swfDictType_t type ) {
if ( dictionary.Num() < characterID + 1 ) {
idLib::Warning( "%s: Could not find character %d", filename.c_str(), characterID );
return NULL;
}
if ( dictionary[ characterID ].type != type ) {
idLib::Warning( "%s: Character %d is the wrong type", filename.c_str(), characterID );
return NULL;
}
return &dictionary[ characterID ];
}
/*
========================
FindDictionaryEntry
========================
*/
idSWFDictionaryEntry * idSWF::FindDictionaryEntry( int characterID ) {
if ( dictionary.Num() < characterID + 1 ) {
idLib::Warning( "%s: Could not find character %d", filename.c_str(), characterID );
return NULL;
}
return &dictionary[ characterID ];
}

222
neo/swf/SWF_Enums.h Normal file
View File

@@ -0,0 +1,222 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_ENUMS_H__
#define __SWF_ENUMS_H__
enum swfDictType_t {
SWF_DICT_NULL,
SWF_DICT_IMAGE,
SWF_DICT_SHAPE,
SWF_DICT_MORPH,
SWF_DICT_SPRITE,
SWF_DICT_FONT,
SWF_DICT_TEXT,
SWF_DICT_EDITTEXT
};
enum swfTag_t {
Tag_End = 0,
Tag_ShowFrame = 1,
Tag_DefineShape = 2,
Tag_PlaceObject = 4,
Tag_RemoveObject = 5,
Tag_DefineBits = 6,
Tag_DefineButton = 7,
Tag_JPEGTables = 8,
Tag_SetBackgroundColor = 9,
Tag_DefineFont = 10,
Tag_DefineText = 11,
Tag_DoAction = 12,
Tag_DefineFontInfo = 13,
Tag_DefineSound = 14,
Tag_StartSound = 15,
Tag_DefineButtonSound = 17,
Tag_SoundStreamHead = 18,
Tag_SoundStreamBlock = 19,
Tag_DefineBitsLossless = 20,
Tag_DefineBitsJPEG2 = 21,
Tag_DefineShape2 = 22,
Tag_DefineButtonCxform = 23,
Tag_Protect = 24,
Tag_PlaceObject2 = 26,
Tag_RemoveObject2 = 28,
Tag_DefineShape3 = 32,
Tag_DefineText2 = 33,
Tag_DefineButton2 = 34,
Tag_DefineBitsJPEG3 = 35,
Tag_DefineBitsLossless2 = 36,
Tag_DefineEditText = 37,
Tag_DefineSprite = 39,
Tag_FrameLabel = 43,
Tag_SoundStreamHead2 = 45,
Tag_DefineMorphShape = 46,
Tag_DefineFont2 = 48,
Tag_ExportAssets = 56,
Tag_ImportAssets = 57,
Tag_EnableDebugger = 58,
Tag_DoInitAction = 59,
Tag_DefineVideoStream = 60,
Tag_VideoFrame = 61,
Tag_DefineFontInfo2 = 62,
Tag_EnableDebugger2 = 64,
Tag_ScriptLimits = 65,
Tag_SetTabIndex = 66,
Tag_FileAttributes = 69,
Tag_PlaceObject3 = 70,
Tag_ImportAssets2 = 71,
Tag_DefineFontAlignZones = 73,
Tag_CSMTextSettings = 74,
Tag_DefineFont3 = 75,
Tag_SymbolClass = 76,
Tag_Metadata = 77,
Tag_DefineScalingGrid = 78,
Tag_DoABC = 82,
Tag_DefineShape4 = 83,
Tag_DefineMorphShape2 = 84,
Tag_DefineSceneAndFrameLabelData = 86,
Tag_DefineBinaryData = 87,
Tag_DefineFontName = 88,
Tag_StartSound2 = 89
};
enum swfAction_t {
Action_End = 0,
// swf 3
Action_NextFrame = 0x04,
Action_PrevFrame = 0x05,
Action_Play = 0x06,
Action_Stop = 0x07,
Action_ToggleQuality = 0x08,
Action_StopSounds = 0x09,
Action_GotoFrame = 0x81,
Action_GetURL = 0x83,
Action_WaitForFrame = 0x8A,
Action_SetTarget = 0x8B,
Action_GoToLabel = 0x8C,
// swf 4
Action_Add = 0x0A,
Action_Subtract = 0x0B,
Action_Multiply = 0x0C,
Action_Divide = 0x0D,
Action_Equals = 0x0E,
Action_Less = 0x0F,
Action_And = 0x10,
Action_Or = 0x11,
Action_Not = 0x12,
Action_StringEquals = 0x13,
Action_StringLength = 0x14,
Action_StringExtract = 0x15,
Action_Pop = 0x17,
Action_ToInteger = 0x18,
Action_GetVariable = 0x1C,
Action_SetVariable = 0x1D,
Action_SetTarget2 = 0x20,
Action_StringAdd = 0x21,
Action_GetProperty = 0x22,
Action_SetProperty = 0x23,
Action_CloneSprite = 0x24,
Action_RemoveSprite = 0x25,
Action_Trace = 0x26,
Action_StartDrag = 0x27,
Action_EndDrag = 0x28,
Action_StringLess = 0x29,
Action_RandomNumber = 0x30,
Action_MBStringLength = 0x31,
Action_CharToAscii = 0x32,
Action_AsciiToChar = 0x33,
Action_GetTime = 0x34,
Action_MBStringExtract = 0x35,
Action_MBCharToAscii = 0x36,
Action_MBAsciiToChar = 0x37,
Action_WaitForFrame2 = 0x8D,
Action_Push = 0x96,
Action_Jump = 0x99,
Action_GetURL2 = 0x9A,
Action_If = 0x9D,
Action_Call = 0x9E,
Action_GotoFrame2 = 0x9F,
// swf 5
Action_Delete = 0x3A,
Action_Delete2 = 0x3B,
Action_DefineLocal = 0x3C,
Action_CallFunction = 0x3D,
Action_Return = 0x3E,
Action_Modulo = 0x3F,
Action_NewObject = 0x40,
Action_DefineLocal2 = 0x41,
Action_InitArray = 0x42,
Action_InitObject = 0x43,
Action_TypeOf = 0x44,
Action_TargetPath = 0x45,
Action_Enumerate = 0x46,
Action_Add2 = 0x47,
Action_Less2 = 0x48,
Action_Equals2 = 0x49,
Action_ToNumber = 0x4A,
Action_ToString = 0x4B,
Action_PushDuplicate = 0x4C,
Action_StackSwap = 0x4D,
Action_GetMember = 0x4E,
Action_SetMember = 0x4F,
Action_Increment = 0x50,
Action_Decrement = 0x51,
Action_CallMethod = 0x52,
Action_NewMethod = 0x53,
Action_BitAnd = 0x60,
Action_BitOr = 0x61,
Action_BitXor = 0x62,
Action_BitLShift = 0x63,
Action_BitRShift = 0x64,
Action_BitURShift = 0x65,
Action_StoreRegister = 0x87,
Action_ConstantPool = 0x88,
Action_With = 0x94,
Action_DefineFunction = 0x9B,
// swf 6
Action_InstanceOf = 0x54,
Action_Enumerate2 = 0x55,
Action_StrictEquals = 0x66,
Action_Greater = 0x67,
Action_StringGreater = 0x68,
// swf 7
Action_Extends = 0x69,
Action_CastOp = 0x2B,
Action_ImplementsOp = 0x2C,
Action_Throw = 0x2A,
Action_Try = 0x8F,
Action_DefineFunction2 = 0x8E,
};
#endif // !__SWF_ENUMS_H__

457
neo/swf/SWF_Events.cpp Normal file
View File

@@ -0,0 +1,457 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
===================
idSWF::HitTest
===================
*/
idSWFScriptObject * idSWF::HitTest( idSWFSpriteInstance * spriteInstance, const swfRenderState_t & renderState, int x, int y, idSWFScriptObject * parentObject ) {
if ( spriteInstance->parent != NULL ) {
swfDisplayEntry_t * thisDisplayEntry = spriteInstance->parent->FindDisplayEntry( spriteInstance->depth );
if ( thisDisplayEntry->cxf.mul.w + thisDisplayEntry->cxf.add.w < 0.001f ) {
return NULL;
}
}
if ( !spriteInstance->isVisible ) {
return NULL;
}
if ( spriteInstance->scriptObject->HasValidProperty( "onRelease" )
|| spriteInstance->scriptObject->HasValidProperty( "onPress" )
|| spriteInstance->scriptObject->HasValidProperty( "onRollOver" )
|| spriteInstance->scriptObject->HasValidProperty( "onRollOut" )
|| spriteInstance->scriptObject->HasValidProperty( "onDrag" )
) {
parentObject = spriteInstance->scriptObject;
}
// rather than returning the first object we find, we actually want to return the last object we find
idSWFScriptObject * returnObject = NULL;
float xOffset = spriteInstance->xOffset;
float yOffset = spriteInstance->yOffset;
for ( int i = 0; i < spriteInstance->displayList.Num(); i++ ) {
const swfDisplayEntry_t & display = spriteInstance->displayList[i];
idSWFDictionaryEntry * entry = FindDictionaryEntry( display.characterID );
if ( entry == NULL ) {
continue;
}
swfRenderState_t renderState2;
renderState2.matrix = display.matrix.Multiply( renderState.matrix );
renderState2.ratio = display.ratio;
if ( entry->type == SWF_DICT_SPRITE ) {
idSWFScriptObject * object = HitTest( display.spriteInstance, renderState2, x, y, parentObject );
if ( object != NULL && object->Get( "_visible" ).ToBool() ) {
returnObject = object;
}
} else if ( entry->type == SWF_DICT_SHAPE && ( parentObject != NULL ) ) {
idSWFShape * shape = entry->shape;
for ( int i = 0; i < shape->fillDraws.Num(); i++ ) {
const idSWFShapeDrawFill & fill = shape->fillDraws[i];
for ( int j = 0; j < fill.indices.Num(); j+=3 ) {
idVec2 xy1 = renderState2.matrix.Transform( fill.startVerts[fill.indices[j+0]] );
idVec2 xy2 = renderState2.matrix.Transform( fill.startVerts[fill.indices[j+1]] );
idVec2 xy3 = renderState2.matrix.Transform( fill.startVerts[fill.indices[j+2]] );
idMat3 edgeEquations;
edgeEquations[0].Set( xy1.x + xOffset, xy1.y + yOffset, 1.0f );
edgeEquations[1].Set( xy2.x + xOffset, xy2.y + yOffset, 1.0f );
edgeEquations[2].Set( xy3.x + xOffset, xy3.y + yOffset, 1.0f );
edgeEquations.InverseSelf();
idVec3 p( x, y, 1.0f );
idVec3 signs = p * edgeEquations;
bool bx = signs.x > 0;
bool by = signs.y > 0;
bool bz = signs.z > 0;
if ( bx == by && bx == bz ) {
// point inside
returnObject = parentObject;
}
}
}
} else if ( entry->type == SWF_DICT_MORPH ) {
// FIXME: this should be roughly the same as SWF_DICT_SHAPE
} else if ( entry->type == SWF_DICT_TEXT ) {
// FIXME: this should be roughly the same as SWF_DICT_SHAPE
} else if ( entry->type == SWF_DICT_EDITTEXT ) {
idSWFScriptObject * editObject = NULL;
if ( display.textInstance->scriptObject.HasProperty( "onRelease" ) || display.textInstance->scriptObject.HasProperty( "onPress" ) ) {
// if the edit box itself can be clicked, then we want to return it when it's clicked on
editObject = &display.textInstance->scriptObject;
} else if ( parentObject != NULL ) {
// otherwise, we want to return the parent object
editObject = parentObject;
}
if ( editObject == NULL ) {
continue;
}
if ( display.textInstance->text.IsEmpty() ) {
continue;
}
const idSWFEditText * shape = entry->edittext;
const idSWFEditText * text = display.textInstance->GetEditText();
float textLength = display.textInstance->GetTextLength();
float lengthDiff = fabs( shape->bounds.br.x - shape->bounds.tl.x ) - textLength;
idVec3 tl;
idVec3 tr;
idVec3 br;
idVec3 bl;
float xOffset = spriteInstance->xOffset;
float yOffset = spriteInstance->yOffset;
float topOffset = 0.0f;
if ( text->align == SWF_ET_ALIGN_LEFT ) {
tl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
tr.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x - lengthDiff + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
br.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x - lengthDiff + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
bl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
} else if ( text->align == SWF_ET_ALIGN_RIGHT ) {
tl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + lengthDiff + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
tr.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
br.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
bl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + lengthDiff + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
} else if ( text->align == SWF_ET_ALIGN_CENTER ) {
float middle = ( ( shape->bounds.br.x + xOffset ) + ( shape->bounds.tl.x + xOffset ) ) / 2.0f;
tl.ToVec2() = renderState2.matrix.Transform( idVec2( middle - ( textLength / 2.0f ), shape->bounds.tl.y + topOffset + yOffset ) );
tr.ToVec2() = renderState2.matrix.Transform( idVec2( middle + ( textLength / 2.0f ), shape->bounds.tl.y + topOffset + yOffset ) );
br.ToVec2() = renderState2.matrix.Transform( idVec2( middle + ( textLength / 2.0f ), shape->bounds.br.y + topOffset + yOffset ) );
bl.ToVec2() = renderState2.matrix.Transform( idVec2( middle - ( textLength / 2.0f ), shape->bounds.br.y + topOffset + yOffset ) );
} else {
tl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
tr.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x + xOffset, shape->bounds.tl.y + topOffset + yOffset ) );
br.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.br.x + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
bl.ToVec2() = renderState2.matrix.Transform( idVec2( shape->bounds.tl.x + xOffset, shape->bounds.br.y + topOffset + yOffset ) );
}
tl.z = 1.0f;
tr.z = 1.0f;
br.z = 1.0f;
bl.z = 1.0f;
idMat3 edgeEquations;
edgeEquations[0] = tl;
edgeEquations[1] = tr;
edgeEquations[2] = br;
edgeEquations.InverseSelf();
idVec3 p( x, y, 1.0f );
idVec3 signs = p * edgeEquations;
bool bx = signs.x > 0;
bool by = signs.y > 0;
bool bz = signs.z > 0;
if ( bx == by && bx == bz ) {
// point inside top right triangle
returnObject = editObject;
}
edgeEquations[0] = tl;
edgeEquations[1] = br;
edgeEquations[2] = bl;
edgeEquations.InverseSelf();
signs = p * edgeEquations;
bx = signs.x > 0;
by = signs.y > 0;
bz = signs.z > 0;
if ( bx == by && bx == bz ) {
// point inside bottom left triangle
returnObject = editObject;
}
}
}
return returnObject;
}
/*
===================
idSWF::HandleEvent
===================
*/
bool idSWF::HandleEvent( const sysEvent_t * event ) {
if ( !IsLoaded() || !IsActive() || ( !inhibitControl && useInhibtControl ) ) {
return false;
}
if ( event->evType == SE_KEY ) {
if ( event->evValue == K_MOUSE1 ) {
mouseEnabled = true;
idSWFScriptVar var;
if ( event->evValue2 ) {
idSWFScriptVar waitInput = globals->Get( "waitInput" );
if ( waitInput.IsFunction() ) {
useMouse = false;
idSWFParmList waitParms;
waitParms.Append( event->evValue );
waitInput.GetFunction()->Call( NULL, waitParms );
waitParms.Clear();
} else {
useMouse = true;
}
idSWFScriptObject * hitObject = HitTest( mainspriteInstance, swfRenderState_t(), mouseX, mouseY, NULL );
if ( hitObject != NULL ) {
mouseObject = hitObject;
mouseObject->AddRef();
var = hitObject->Get( "onPress" );
if ( var.IsFunction() ) {
idSWFParmList parms;
parms.Append( event->inputDevice );
var.GetFunction()->Call( hitObject, parms );
parms.Clear();
return true;
}
idSWFScriptVar var = hitObject->Get( "onDrag" );
if ( var.IsFunction() ) {
idSWFParmList parms;
parms.Append( mouseX );
parms.Append( mouseY );
parms.Append( true );
var.GetFunction()->Call( hitObject, parms );
parms.Clear();
return true;
}
}
idSWFParmList parms;
parms.Append( hitObject );
Invoke( "setHitObject", parms );
} else {
if ( mouseObject ) {
var = mouseObject->Get( "onRelease" );
if ( var.IsFunction() ) {
idSWFParmList parms;
parms.Append( mouseObject ); // FIXME: Remove this
var.GetFunction()->Call( mouseObject, parms );
}
mouseObject->Release();
mouseObject = NULL;
}
if ( hoverObject ) {
hoverObject->Release();
hoverObject = NULL;
}
if ( var.IsFunction() ) {
return true;
}
}
return false;
}
const char * keyName = idKeyInput::KeyNumToString( (keyNum_t)event->evValue );
idSWFScriptVar var = shortcutKeys->Get( keyName );
// anything more than 32 levels of indirection we can be pretty sure is an infinite loop
for ( int runaway = 0; runaway < 32; runaway++ ) {
idSWFParmList eventParms;
eventParms.Clear();
eventParms.Append( event->inputDevice );
if ( var.IsString() ) {
// alias to another key
var = shortcutKeys->Get( var.ToString() );
continue;
} else if ( var.IsObject() ) {
// if this object is a sprite, send fake mouse events to it
idSWFScriptObject * object = var.GetObject();
// make sure we don't send an onRelease event unless we have already sent that object an onPress
bool wasPressed = object->Get( "_pressed" ).ToBool();
object->Set( "_pressed", event->evValue2 );
if ( event->evValue2 ) {
var = object->Get( "onPress" );
} else if ( wasPressed ) {
var = object->Get( "onRelease" );
}
if ( var.IsFunction() ) {
var.GetFunction()->Call( object, eventParms );
return true;
}
} else if ( var.IsFunction() ) {
if ( event->evValue2 ) {
// anonymous functions only respond to key down events
var.GetFunction()->Call( NULL, eventParms );
return true;
}
return false;
}
idSWFScriptVar useFunction = globals->Get( "useFunction" );
if ( useFunction.IsFunction() && event->evValue2 ) {
const char * action = idKeyInput::GetBinding( event->evValue );
if ( idStr::Cmp( "_use", action ) == 0 ) {
useFunction.GetFunction()->Call( NULL, idSWFParmList() );
}
}
idSWFScriptVar waitInput = globals->Get( "waitInput" );
if ( waitInput.IsFunction() ) {
useMouse = false;
if ( event->evValue2 ) {
idSWFParmList waitParms;
waitParms.Append( event->evValue );
waitInput.GetFunction()->Call( NULL, waitParms );
}
} else {
useMouse = true;
}
idSWFScriptVar focusWindow = globals->Get( "focusWindow" );
if ( focusWindow.IsObject() ) {
idSWFScriptVar onKey = focusWindow.GetObject()->Get( "onKey" );
if ( onKey.IsFunction() ) {
// make sure we don't send an onRelease event unless we have already sent that object an onPress
idSWFScriptObject * object = focusWindow.GetObject();
bool wasPressed = object->Get( "_kpressed" ).ToBool();
object->Set( "_kpressed", event->evValue2 );
if ( event->evValue2 || wasPressed ) {
idSWFParmList parms;
parms.Append( event->evValue );
parms.Append( event->evValue2 );
onKey.GetFunction()->Call( focusWindow.GetObject(), parms ).ToBool();
return true;
} else if ( event->evValue == K_LSHIFT || event->evValue == K_RSHIFT ) {
idSWFParmList parms;
parms.Append( event->evValue );
parms.Append( event->evValue2 );
onKey.GetFunction()->Call( focusWindow.GetObject(), parms ).ToBool();
}
}
}
return false;
}
idLib::Warning( "Circular reference in %s shortcutKeys.%s", filename.c_str(), keyName );
} else if ( event->evType == SE_CHAR ) {
idSWFScriptVar focusWindow = globals->Get( "focusWindow" );
if ( focusWindow.IsObject() ) {
idSWFScriptVar onChar = focusWindow.GetObject()->Get( "onChar" );
if ( onChar.IsFunction() ) {
idSWFParmList parms;
parms.Append( event->evValue );
parms.Append( idKeyInput::KeyNumToString( (keyNum_t)event->evValue ) );
onChar.GetFunction()->Call( focusWindow.GetObject(), parms ).ToBool();
return true;
}
}
} else if ( event->evType == SE_MOUSE_ABSOLUTE || event->evType == SE_MOUSE ) {
mouseEnabled = true;
isMouseInClientArea = true;
// Mouse position in screen space needs to be converted to SWF space
if ( event->evType == SE_MOUSE_ABSOLUTE ) {
const float pixelAspect = renderSystem->GetPixelAspect();
const float sysWidth = renderSystem->GetWidth() * ( pixelAspect > 1.0f ? pixelAspect : 1.0f );
const float sysHeight = renderSystem->GetHeight() / ( pixelAspect < 1.0f ? pixelAspect : 1.0f );
float scale = swfScale * sysHeight / (float)frameHeight;
float invScale = 1.0f / scale;
float tx = 0.5f * ( sysWidth - ( frameWidth * scale ) );
float ty = 0.5f * ( sysHeight - ( frameHeight * scale ) );
mouseX = idMath::Ftoi( ( static_cast<float>( event->evValue ) - tx ) * invScale );
mouseY = idMath::Ftoi( ( static_cast<float>( event->evValue2 ) - ty ) * invScale );
} else {
mouseX += event->evValue;
mouseY += event->evValue2;
mouseX = Max( Min( mouseX, idMath::Ftoi( frameWidth + renderBorder ) ), idMath::Ftoi( 0.0f - renderBorder ) );
mouseY = Max( Min( mouseY, idMath::Ftoi(frameHeight) ), 0 );
}
bool retVal = false;
idSWFScriptObject * hitObject = HitTest( mainspriteInstance, swfRenderState_t(), mouseX, mouseY, NULL );
if ( hitObject != NULL ) {
hasHitObject = true;
} else {
hasHitObject = false;
}
if ( hitObject != hoverObject ) {
// First check to see if we should call onRollOut on our previous hoverObject
if ( hoverObject != NULL ) {
idSWFScriptVar var = hoverObject->Get( "onRollOut" );
if ( var.IsFunction() ) {
var.GetFunction()->Call( hoverObject, idSWFParmList() );
retVal = true;
}
hoverObject->Release();
hoverObject = NULL;
}
// Then call onRollOver on our hitObject
if ( hitObject != NULL ) {
hoverObject = hitObject;
hoverObject->AddRef();
idSWFScriptVar var = hitObject->Get( "onRollOver" );
if ( var.IsFunction() ) {
var.GetFunction()->Call( hitObject, idSWFParmList() );
retVal = true;
}
}
}
if ( mouseObject != NULL ) {
idSWFScriptVar var = mouseObject->Get( "onDrag" );
if ( var.IsFunction() ) {
idSWFParmList parms;
parms.Append( mouseX );
parms.Append( mouseY );
parms.Append( false );
var.GetFunction()->Call( mouseObject, parms );
return true;
}
}
return retVal;
} else if ( event->evType == SE_MOUSE_LEAVE ) {
isMouseInClientArea = false;
} else if ( event->evType == SE_JOYSTICK ) {
idSWFParmList parms;
parms.Append( event->evValue );
parms.Append( event->evValue2 / 32.0f );
Invoke( "onJoystick", parms );
}
return false;
}

575
neo/swf/SWF_Image.cpp Normal file
View File

@@ -0,0 +1,575 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "../renderer/Image.h"
//#include "../../renderer/ImageTools/ImageProcess.h"
#include "../renderer/jpeg-6/jpeglib.h"
/*
========================
idSWF::idDecompressJPEG
These are the static callback functions the jpeg library calls
========================
*/
void swf_jpeg_error_exit( jpeg_common_struct * cinfo ) {
char buffer[JMSG_LENGTH_MAX] = {0};
(*cinfo->err->format_message)( cinfo, buffer );
throw idException( buffer );
}
void swf_jpeg_output_message( jpeg_common_struct * cinfo ) {
char buffer[JMSG_LENGTH_MAX] = {0};
(*cinfo->err->format_message)( cinfo, buffer );
idLib::Printf( "%s\n", buffer );
}
void swf_jpeg_init_source( jpeg_decompress_struct * cinfo ) {
}
boolean swf_jpeg_fill_input_buffer( jpeg_decompress_struct * cinfo ) {
return TRUE;
}
void swf_jpeg_skip_input_data( jpeg_decompress_struct * cinfo, long num_bytes ) {
cinfo->src->next_input_byte += num_bytes;
cinfo->src->bytes_in_buffer -= num_bytes;
}
void swf_jpeg_term_source( jpeg_decompress_struct * cinfo ) {
}
/*
========================
idSWF::idDecompressJPEG::idDecompressJPEG
========================
*/
idSWF::idDecompressJPEG::idDecompressJPEG() {
jpeg_decompress_struct * cinfo = new (TAG_SWF) jpeg_decompress_struct;
memset( cinfo, 0, sizeof( *cinfo ) );
cinfo->err = new (TAG_SWF) jpeg_error_mgr;
memset( cinfo->err, 0, sizeof( jpeg_error_mgr ) );
jpeg_std_error( cinfo->err );
cinfo->err->error_exit = swf_jpeg_error_exit;
cinfo->err->output_message = swf_jpeg_output_message;
jpeg_create_decompress( cinfo );
vinfo = cinfo;
}
/*
========================
idSWF::idDecompressJPEG::~idDecompressJPEG
========================
*/
idSWF::idDecompressJPEG::~idDecompressJPEG() {
jpeg_decompress_struct * cinfo = (jpeg_decompress_struct *)vinfo;
jpeg_destroy_decompress( cinfo );
delete cinfo->err;
delete cinfo;
}
/*
========================
idSWF::idDecompressJPEG::Load
========================
*/
byte * idSWF::idDecompressJPEG::Load( const byte * input, int inputSize, int & width, int & height ) {
jpeg_decompress_struct * cinfo = (jpeg_decompress_struct *)vinfo;
try {
width = 0;
height = 0;
jpeg_source_mgr src;
memset( &src, 0, sizeof( src ) );
src.next_input_byte = (JOCTET *)input;
src.bytes_in_buffer = inputSize;
src.init_source = swf_jpeg_init_source;
src.fill_input_buffer = swf_jpeg_fill_input_buffer;
src.skip_input_data = swf_jpeg_skip_input_data;
src.resync_to_restart = jpeg_resync_to_restart;
src.term_source = swf_jpeg_term_source;
cinfo->src = &src;
int result = 0;
do {
result = jpeg_read_header( cinfo, FALSE );
} while ( result == JPEG_HEADER_TABLES_ONLY );
if ( result == JPEG_SUSPENDED ) {
return NULL;
}
jpeg_start_decompress( cinfo );
if ( cinfo->output_components != 4 ) {
// This shouldn't really be possible, unless the source image is some kind of strange grayscale format or something
idLib::Warning( "JPEG output is not 4 components" );
jpeg_abort_decompress( cinfo );
cinfo->src = NULL; // value goes out of scope
return NULL;
}
int outputSize = cinfo->output_width * cinfo->output_height * cinfo->output_components;
byte * output = (byte *)Mem_Alloc( outputSize, TAG_SWF );
memset( output, 255, outputSize );
while ( cinfo->output_scanline < cinfo->output_height ) {
JSAMPROW scanlines = output + cinfo->output_scanline * cinfo->output_width * cinfo->output_components;
jpeg_read_scanlines( cinfo, &scanlines, 1 );
}
jpeg_finish_decompress( cinfo );
width = cinfo->output_width;
height = cinfo->output_height;
cinfo->src = NULL; // value goes out of scope
return output;
} catch ( idException & ) {
swf_jpeg_output_message( (jpeg_common_struct *)cinfo );
return NULL;
}
}
/*
========================
idSWF::WriteSwfImageAtlas
Now that all images have been found, allocate them in an atlas
and write it out.
========================
*/
void RectAllocator( const idList<idVec2i> &inputSizes, idList<idVec2i> &outputPositions, idVec2i &totalSize );
float RectPackingFraction( const idList<idVec2i> &inputSizes, const idVec2i totalSize );
void idSWF::WriteSwfImageAtlas( const char *filename ) {
idList<idVec2i> inputSizes;
inputSizes.SetNum( packImages.Num() );
for ( int i = 0 ; i < packImages.Num() ; i++ ) {
// these are in DXT blocks, not pixels
inputSizes[i] = packImages[i].allocSize;
}
idList<idVec2i> outputPositions;
idVec2i totalSize;
// smart allocator
RectAllocator( inputSizes, outputPositions, totalSize );
float frac = RectPackingFraction( inputSizes, totalSize );
idLib::Printf( "%5.2f packing fraction in %ix%i image\n", frac, totalSize.x*4, totalSize.y*4 );
int atlasWidth = Max( 4, totalSize.x * 4 ) ;
int atlasHeight = Max( 4, totalSize.y * 4 ) ;
// we require multiple-of-128 widths to use the image data directly
// without re-packing on the 360 and PS3. The growth checks in RectAllocator()
// will always align, but a single image won't necessarily be.
atlasWidth = ( atlasWidth + 127 ) & ~127;
idTempArray<byte> swfAtlas( atlasWidth * atlasHeight * 4 );
// fill everything with solid red
for ( int i = 0; i < atlasWidth * atlasHeight; i++ ) {
swfAtlas[i*4+0] = 255;
swfAtlas[i*4+1] = 0;
swfAtlas[i*4+2] = 0;
swfAtlas[i*4+3] = 255;
}
// allocate the blocks and copy the texels
for ( int i = 0 ; i < packImages.Num() ; i++ ) {
imageToPack_t & pack = packImages[i];
assert( pack.imageData != NULL );
int blockWidth = pack.allocSize.x;
int blockHeight = pack.allocSize.y;
int x = outputPositions[i].x;
int y = outputPositions[i].y;
// get the range for each channel so we can maximize it
// for better compression
int minV[4] = { 255, 255, 255, 255 };
int maxV[4] = { 0, 0, 0, 0 };
for ( int j = 0 ; j < pack.trueSize.x * pack.trueSize.y * 4 ; j++ ) {
int v = pack.imageData[ j ];
int x = j & 3;
if ( v < minV[x] ) {
minV[x] = v;
}
if ( v > maxV[x] ) {
maxV[x] = v;
}
}
// idLib::Printf( "Color normalize: %3i:%3i %3i:%3i %3i:%3i %3i:%3i\n",
// minV[0], maxV[0], minV[1], maxV[1], minV[2], maxV[2], minV[3], maxV[3] );
// don't divide by zero
for ( int x = 0 ; x < 4 ; x++ ) {
if ( maxV[x] == 0 ) {
maxV[x] = 1;
}
}
// rescale the image
//
// Note that this must be done in RGBA space, before YCoCg conversion,
// or the scale factors couldn't be combined with the normal swf coloring.
//
// If we create an idMaterial for each atlas element, we could add
// a bias as well as a scale to enable us to take advantage of the
// min values as well as the max, but very few gui images don't go to black,
// and just doing a scale avoids changing more code.
for ( int j = 0; j < pack.trueSize.x * pack.trueSize.y * 4; j++ ) {
int v = pack.imageData[ j ];
int x = j & 3;
v = v * 255 / maxV[x];
pack.imageData[ j ] = v;
}
assert( ( x + blockWidth )* 4 <= atlasWidth );
assert( ( y + blockHeight )* 4 <= atlasHeight );
// Extend the pixels with clamp-to-edge to the edge of the allocation block.
// The GPU hardware addressing should completely ignore texels outside the true block
// size, but the compressor works on complete blocks, regardless of the true rect size.
x <<= 2;
y <<= 2;
for ( int dstY = 0; dstY < blockHeight<<2; dstY++ ) {
int srcY = dstY-1;
if ( srcY < 0 ) {
srcY = 0;
}
if ( srcY >= pack.trueSize.y ) {
srcY = pack.trueSize.y - 1;
}
for ( int dstX = 0 ; dstX < blockWidth<<2 ; dstX++ ) {
int srcX = dstX-1;
if ( srcX < 0 ) {
srcX = 0;
}
if ( srcX >= pack.trueSize.x ) {
srcX = pack.trueSize.x - 1;
}
((int *)swfAtlas.Ptr())[ (y+dstY) * atlasWidth + (x+dstX) ] =
((int *)pack.imageData)[ srcY * pack.trueSize.x + srcX ];
}
}
// save the information in the SWF dictionary
idSWFDictionaryEntry * entry = FindDictionaryEntry( pack.characterID );
assert( entry->material == NULL );
entry->imageSize.x = pack.trueSize.x;
entry->imageSize.y = pack.trueSize.y;
entry->imageAtlasOffset.x = x + 1;
entry->imageAtlasOffset.y = y + 1;
for ( int i = 0; i < 4; i++ ) {
entry->channelScale[i] = maxV[i] / 255.0f;
}
Mem_Free( pack.imageData );
pack.imageData = NULL;
}
// the TGA is only for examination during development
R_WriteTGA( filename, swfAtlas.Ptr(), atlasWidth, atlasHeight, false, "fs_basepath" );
}
/*
========================
idSWF::LoadImage
Loads RGBA data into an image at the specificied character id in the dictionary
========================
*/
void idSWF::LoadImage( int characterID, const byte * imageData, int width, int height ) {
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_IMAGE );
if ( entry == NULL ) {
return;
}
// save the data off so we can do the image atlas allocation after we have collected
// all the images that are used by the entire swf
imageToPack_t pack;
pack.characterID = characterID;
pack.imageData = (byte *)Mem_Alloc( width*height*4, TAG_SWF );
memcpy( pack.imageData, imageData, width*height*4 );
pack.trueSize.x = width;
pack.trueSize.y = height;
for ( int i = 0 ; i < 2 ; i++ ) {
int v = pack.trueSize[i];
// Swf images are usually completely random in size, but perform all allocations in
// DXT blocks of 4. If we choose to DCT / HDP encode the image block, we should probably
// increae the block size to 8 or 16 to prevent neighbor effects.
v = ( v + 3 ) >> 2;
// Allways allocate a single pixel border around the images so there won't be any edge
// bleeds. This can often be hidden in in the round-up to DXT size.
if ( ( v << 2 ) - pack.trueSize[i] < 2 ) {
v++;
}
pack.allocSize[i] = v;
}
packImages.Append( pack );
entry->material = NULL;
}
/*
========================
idSWF::JPEGTables
Reads jpeg table data, there can only be one of these in the file, and it has to come before any DefineBits tags
We don't have to worry about clearing the jpeg object because jpeglib will automagically overwrite any tables that are already set (I think?)
========================
*/
void idSWF::JPEGTables( idSWFBitStream & bitstream ) {
if ( bitstream.Length() == 0 ) {
// no clue why this happens
return;
}
int width, height;
jpeg.Load( bitstream.ReadData( bitstream.Length() ), bitstream.Length(), width, height );
}
/*
========================
idSWF::DefineBits
Reads a partial jpeg image, using the tables set by the JPEGTables tag
========================
*/
void idSWF::DefineBits( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
int jpegSize = bitstream.Length() - sizeof( uint16 );
int width, height;
byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
if ( imageData == NULL ) {
return;
}
LoadImage( characterID, imageData, width, height );
Mem_Free( imageData );
}
/*
========================
idSWF::DefineBitsJPEG2
Identical to DefineBits, except it uses a local JPEG table (not the one defined by JPEGTables)
========================
*/
void idSWF::DefineBitsJPEG2( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idDecompressJPEG jpeg;
int jpegSize = bitstream.Length() - sizeof( uint16 );
int width, height;
byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
if ( imageData == NULL ) {
return;
}
LoadImage( characterID, imageData, width, height );
Mem_Free( imageData );
}
/*
========================
idSWF::DefineBitsJPEG3
Mostly identical to DefineBitsJPEG2, except it has an additional zlib compressed alpha map
========================
*/
void idSWF::DefineBitsJPEG3( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
uint32 jpegSize = bitstream.ReadU32();
idDecompressJPEG jpeg;
int width, height;
byte * imageData = jpeg.Load( bitstream.ReadData( jpegSize ), jpegSize, width, height );
if ( imageData == NULL ) {
return;
}
{
idTempArray<byte> alphaMap( width * height );
int alphaSize = bitstream.Length() - jpegSize - sizeof( characterID ) - sizeof( jpegSize );
if ( !Inflate( bitstream.ReadData( alphaSize ), alphaSize, alphaMap.Ptr(), (int)alphaMap.Size() ) ) {
idLib::Warning( "DefineBitsJPEG3: Failed to inflate alpha data" );
Mem_Free( imageData );
return;
}
for ( int i = 0; i < width * height; i++ ) {
imageData[i*4+3] = alphaMap[i];
}
}
LoadImage( characterID, imageData, width, height );
Mem_Free( imageData );
}
/*
========================
idSWF::DefineBitsLossless
========================
*/
void idSWF::DefineBitsLossless( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
uint8 format = bitstream.ReadU8();
uint16 width = bitstream.ReadU16();
uint16 height = bitstream.ReadU16();
idTempArray< byte > buf( width * height * 4 );
byte * imageData = buf.Ptr();
if ( format == 3 ) {
uint32 paddedWidth = ( width + 3 ) & ~3;
uint32 colorTableSize = ( bitstream.ReadU8() + 1 ) * 3;
idTempArray<byte> colorMapData( colorTableSize + ( paddedWidth * height ) );
uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, colorMapData.Ptr(), (int)colorMapData.Size() ) ) {
idLib::Warning( "DefineBitsLossless: Failed to inflate color map data" );
return;
}
byte * indices = colorMapData.Ptr() + colorTableSize;
for ( int h = 0; h < height; h++ ) {
for ( int w = 0; w < width; w++ ) {
byte index = indices[w + (h*paddedWidth)];
byte * pixel = &imageData[(w + (h*width)) * 4];
pixel[0] = colorMapData[index * 3 + 0];
pixel[1] = colorMapData[index * 3 + 1];
pixel[2] = colorMapData[index * 3 + 2];
pixel[3] = 0xFF;
}
}
} else if ( format == 4 ) {
uint32 paddedWidth = ( width + 1 ) & 1;
idTempArray<uint16> bitmapData( paddedWidth * height * 2 );
uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
idLib::Warning( "DefineBitsLossless: Failed to inflate bitmap data" );
return;
}
for ( int h = 0; h < height; h++ ) {
for ( int w = 0; w < width; w++ ) {
uint16 pix15 = bitmapData[w + (h*paddedWidth)];
idSwap::Big( pix15 );
byte * pixel = &imageData[(w + (h*width)) * 4];
pixel[0] = ( pix15 >> 10 ) & 0x1F;
pixel[1] = ( pix15 >> 5 ) & 0x1F;
pixel[2] = ( pix15 >> 0 ) & 0x1F;
pixel[3] = 0xFF;
}
}
} else if ( format == 5 ) {
idTempArray<uint32> bitmapData( width * height );
uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
idLib::Warning( "DefineBitsLossless: Failed to inflate bitmap data" );
return;
}
for ( int h = 0; h < height; h++ ) {
for ( int w = 0; w < width; w++ ) {
uint32 pix24 = bitmapData[w + (h*width)];
idSwap::Big( pix24 );
byte * pixel = &imageData[(w + (h*width)) * 4];
pixel[0] = ( pix24 >> 16 ) & 0xFF;
pixel[1] = ( pix24 >> 8 ) & 0xFF;
pixel[2] = ( pix24 >> 0 ) & 0xFF;
pixel[3] = 0xFF;
}
}
} else {
idLib::Warning( "DefineBitsLossless: Unknown image format %d", format );
memset( imageData, 0xFF, width * height * 4 );
}
LoadImage( characterID, imageData, width, height );
}
/*
========================
idSWF::DefineBitsLossless2
========================
*/
void idSWF::DefineBitsLossless2( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
uint8 format = bitstream.ReadU8();
uint16 width = bitstream.ReadU16();
uint16 height = bitstream.ReadU16();
idTempArray< byte > buf( width * height * 4 );
byte * imageData = buf.Ptr();
if ( format == 3 ) {
uint32 paddedWidth = ( width + 3 ) & ~3;
uint32 colorTableSize = ( bitstream.ReadU8() + 1 ) * 4;
idTempArray<byte> colorMapData( colorTableSize + ( paddedWidth * height ) );
uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, colorMapData.Ptr(), (int)colorMapData.Size() ) ) {
idLib::Warning( "DefineBitsLossless2: Failed to inflate color map data" );
return;
}
byte * indices = colorMapData.Ptr() + colorTableSize;
for ( int h = 0; h < height; h++ ) {
for ( int w = 0; w < width; w++ ) {
byte index = indices[w + (h*paddedWidth)];
byte * pixel = &imageData[(w + (h*width)) * 4];
pixel[0] = colorMapData[index * 4 + 0];
pixel[1] = colorMapData[index * 4 + 1];
pixel[2] = colorMapData[index * 4 + 2];
pixel[3] = colorMapData[index * 4 + 3];
}
}
} else if ( format == 5 ) {
idTempArray<uint32> bitmapData( width * height );
uint32 colorDataSize = bitstream.Length() - bitstream.Tell();
if ( !Inflate( bitstream.ReadData( colorDataSize ), colorDataSize, (byte *)bitmapData.Ptr(), (int)bitmapData.Size() ) ) {
idLib::Warning( "DefineBitsLossless2: Failed to inflate bitmap data" );
return;
}
for ( int h = 0; h < height; h++ ) {
for ( int w = 0; w < width; w++ ) {
uint32 pix32 = bitmapData[w + (h*width)];
idSwap::Big( pix32 );
byte * pixel = &imageData[(w + (h*width)) * 4];
pixel[0] = ( pix32 >> 16 ) & 0xFF;
pixel[1] = ( pix32 >> 8 ) & 0xFF;
pixel[2] = ( pix32 >> 0 ) & 0xFF;
pixel[3] = ( pix32 >> 24 ) & 0xFF;
}
}
} else {
idLib::Warning( "DefineBitsLossless2: Unknown image format %d", format );
memset( imageData, 0xFF, width * height * 4 );
}
LoadImage( characterID, imageData, width, height );
}

458
neo/swf/SWF_Load.cpp Normal file
View File

@@ -0,0 +1,458 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "../renderer/Font.h"
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
#define BSWF_VERSION 16 // bumped to 16 for storing atlas image dimensions for unbuffered loads
#define BSWF_MAGIC ( ( 'B' << 24 ) | ( 'S' << 16 ) | ( 'W' << 8 ) | BSWF_VERSION )
/*
===================
idSWF::LoadSWF
===================
*/
bool idSWF::LoadSWF( const char * fullpath ) {
idFile * rawfile = fileSystem->OpenFileRead( fullpath );
if ( rawfile == NULL ) {
idLib::Printf( "SWF File not found %s\n", fullpath );
return false;
}
swfHeader_t header;
rawfile->Read( &header, sizeof( header ) );
if ( header.W != 'W' || header.S != 'S' ) {
idLib::Warning( "Wrong signature bytes" );
delete rawfile;
return false;
}
if ( header.version > 9 ) {
idLib::Warning( "Unsupported version %d", header.version );
delete rawfile;
return false;
}
bool compressed;
if ( header.compression == 'F' ) {
compressed = false;
} else if ( header.compression == 'C' ) {
compressed = true;
} else {
idLib::Warning( "Unsupported compression type %c", header.compression );
delete rawfile;
return false;
}
idSwap::Little( header.fileLength );
// header.fileLength somewhat annoyingly includes the size of the header
uint32 fileLength2 = header.fileLength - (uint32)sizeof( swfHeader_t );
// slurp the raw file into a giant array, which is somewhat atrocious when loading from the preload since it's already an idFile_Memory
byte * fileData = (byte *)Mem_Alloc( fileLength2, TAG_SWF );
size_t fileSize = rawfile->Read( fileData, fileLength2 );
delete rawfile;
if ( compressed ) {
byte * uncompressed = (byte *)Mem_Alloc( fileLength2, TAG_SWF );
if ( !Inflate( fileData, (int)fileSize, uncompressed, fileLength2 ) ) {
idLib::Warning( "Inflate error" );
Mem_Free( uncompressed );
return false;
}
Mem_Free( fileData );
fileData = uncompressed;
}
idSWFBitStream bitstream( fileData, fileLength2, false );
swfRect_t frameSize;
bitstream.ReadRect( frameSize );
if ( !frameSize.tl.Compare( vec2_zero ) ) {
idLib::Warning( "Invalid frameSize top left" );
Mem_Free( fileData );
return false;
}
frameWidth = frameSize.br.x;
frameHeight = frameSize.br.y;
frameRate = bitstream.ReadU16();
// parse everything
mainsprite->Load( bitstream, true );
// now that all images have been loaded, write out the combined image
idStr atlasFileName = "generated/";
atlasFileName += fullpath;
atlasFileName.SetFileExtension( ".tga" );
WriteSwfImageAtlas( atlasFileName );
Mem_Free( fileData );
return true;
}
/*
===================
idSWF::LoadBinary
===================
*/
bool idSWF::LoadBinary( const char * bfilename, ID_TIME_T sourceTime ) {
idFile * f = fileSystem->OpenFileReadMemory( bfilename );
if ( f == NULL || f->Length() <= 0 ) {
return false;
}
uint32 magic = 0;
ID_TIME_T btimestamp = 0;
f->ReadBig( magic );
f->ReadBig( btimestamp );
if ( magic != BSWF_MAGIC || ( !fileSystem->InProductionMode() && sourceTime != btimestamp ) ) {
delete f;
return false;
}
f->ReadBig( frameWidth );
f->ReadBig( frameHeight );
f->ReadBig( frameRate );
if ( mouseX == -1 ) {
mouseX = ( frameWidth / 2 );
}
if ( mouseY == -1 ) {
mouseY = ( frameHeight / 2 );
}
mainsprite->Read( f );
int num = 0;
f->ReadBig( num );
dictionary.SetNum( num );
for ( int i = 0; i < dictionary.Num(); i++ ) {
f->ReadBig( dictionary[i].type );
switch ( dictionary[i].type ) {
case SWF_DICT_IMAGE: {
idStr imageName;
f->ReadString( imageName );
if ( imageName[0] == '.' ) {
// internal image in the atlas
dictionary[i].material = NULL;
} else {
dictionary[i].material = declManager->FindMaterial( imageName );
}
for ( int j = 0 ; j < 2 ; j++ ) {
f->ReadBig( dictionary[i].imageSize[j] );
f->ReadBig( dictionary[i].imageAtlasOffset[j] );
}
for ( int j = 0 ; j < 4 ; j++ ) {
f->ReadBig( dictionary[i].channelScale[j] );
}
break;
}
case SWF_DICT_MORPH:
case SWF_DICT_SHAPE: {
dictionary[i].shape = new (TAG_SWF) idSWFShape;
idSWFShape * shape = dictionary[i].shape;
f->ReadBig( shape->startBounds.tl );
f->ReadBig( shape->startBounds.br );
f->ReadBig( shape->endBounds.tl );
f->ReadBig( shape->endBounds.br );
f->ReadBig( num ); shape->fillDraws.SetNum( num );
for ( int d = 0; d < shape->fillDraws.Num(); d++ ) {
idSWFShapeDrawFill & fillDraw = shape->fillDraws[d];
f->ReadBig( fillDraw.style.type );
f->ReadBig( fillDraw.style.subType );
f->Read( &fillDraw.style.startColor, 4 );
f->Read( &fillDraw.style.endColor, 4 );
f->ReadBigArray( (float *)&fillDraw.style.startMatrix, 6 );
f->ReadBigArray( (float *)&fillDraw.style.endMatrix, 6 );
f->ReadBig( fillDraw.style.gradient.numGradients );
for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) {
f->ReadBig( fillDraw.style.gradient.gradientRecords[g].startRatio );
f->ReadBig( fillDraw.style.gradient.gradientRecords[g].endRatio );
f->Read( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 );
f->Read( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 );
}
f->ReadBig( fillDraw.style.focalPoint );
f->ReadBig( fillDraw.style.bitmapID );
f->ReadBig( num ); fillDraw.startVerts.SetNum( num );
f->ReadBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() );
f->ReadBig( num ); fillDraw.endVerts.SetNum( num );
f->ReadBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() );
f->ReadBig( num ); fillDraw.indices.SetNum( num );
f->ReadBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() );
}
f->ReadBig( num ); shape->lineDraws.SetNum( num );
for ( int d = 0; d < shape->lineDraws.Num(); d++ ) {
idSWFShapeDrawLine & lineDraw = shape->lineDraws[d];
f->ReadBig( lineDraw.style.startWidth );
f->ReadBig( lineDraw.style.endWidth );
f->Read( &lineDraw.style.startColor, 4 );
f->Read( &lineDraw.style.endColor, 4 );
f->ReadBig( num ); lineDraw.startVerts.SetNum( num );
f->ReadBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() );
f->ReadBig( num ); lineDraw.endVerts.SetNum( num );
f->ReadBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() );
f->ReadBig( num ); lineDraw.indices.SetNum( num );
f->ReadBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() );
}
break;
}
case SWF_DICT_SPRITE: {
dictionary[i].sprite = new (TAG_SWF) idSWFSprite( this );
dictionary[i].sprite->Read( f );
break;
}
case SWF_DICT_FONT: {
dictionary[i].font = new (TAG_SWF) idSWFFont;
idSWFFont * font = dictionary[i].font;
idStr fontName;
f->ReadString( fontName );
font->fontID = renderSystem->RegisterFont( fontName );
f->ReadBig( font->ascent );
f->ReadBig( font->descent );
f->ReadBig( font->leading );
f->ReadBig( num ); font->glyphs.SetNum( num );
for ( int g = 0; g < font->glyphs.Num(); g++ ) {
f->ReadBig( font->glyphs[g].code );
f->ReadBig( font->glyphs[g].advance );
f->ReadBig( num ); font->glyphs[g].verts.SetNum( num );
f->ReadBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() );
f->ReadBig( num ); font->glyphs[g].indices.SetNum( num );
f->ReadBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() );
}
break;
}
case SWF_DICT_TEXT: {
dictionary[i].text = new (TAG_SWF) idSWFText;
idSWFText * text = dictionary[i].text;
f->ReadBig( text->bounds.tl );
f->ReadBig( text->bounds.br );
f->ReadBigArray( (float *)&text->matrix, 6 );
f->ReadBig( num ); text->textRecords.SetNum( num );
for ( int t = 0; t < text->textRecords.Num(); t++ ) {
idSWFTextRecord & textRecord = text->textRecords[t];
f->ReadBig( textRecord.fontID );
f->Read( &textRecord.color, 4 );
f->ReadBig( textRecord.xOffset );
f->ReadBig( textRecord.yOffset );
f->ReadBig( textRecord.textHeight );
f->ReadBig( textRecord.firstGlyph );
f->ReadBig( textRecord.numGlyphs );
}
f->ReadBig( num ); text->glyphs.SetNum( num );
for ( int g = 0; g < text->glyphs.Num(); g++ ) {
f->ReadBig( text->glyphs[g].index );
f->ReadBig( text->glyphs[g].advance );
}
break;
}
case SWF_DICT_EDITTEXT: {
dictionary[i].edittext = new (TAG_SWF) idSWFEditText;
idSWFEditText * edittext = dictionary[i].edittext;
f->ReadBig( edittext->bounds.tl );
f->ReadBig( edittext->bounds.br );
f->ReadBig( edittext->flags );
f->ReadBig( edittext->fontID );
f->ReadBig( edittext->fontHeight );
f->Read( &edittext->color, 4 );
f->ReadBig( edittext->maxLength );
f->ReadBig( edittext->align );
f->ReadBig( edittext->leftMargin );
f->ReadBig( edittext->rightMargin );
f->ReadBig( edittext->indent );
f->ReadBig( edittext->leading );
f->ReadString( edittext->variable );
f->ReadString( edittext->initialText );
break;
}
}
}
delete f;
return true;
}
/*
===================
idSWF::WriteBinary
===================
*/
void idSWF::WriteBinary( const char * bfilename ) {
idFileLocal file( fileSystem->OpenFileWrite( bfilename, "fs_basepath" ) );
if ( file == NULL ) {
return;
}
file->WriteBig( BSWF_MAGIC );
file->WriteBig( timestamp );
file->WriteBig( frameWidth );
file->WriteBig( frameHeight );
file->WriteBig( frameRate );
mainsprite->Write( file );
file->WriteBig( dictionary.Num() );
for ( int i = 0; i < dictionary.Num(); i++ ) {
file->WriteBig( dictionary[i].type );
switch ( dictionary[i].type ) {
case SWF_DICT_IMAGE: {
if ( dictionary[i].material ) {
file->WriteString( dictionary[i].material->GetName() );
} else {
file->WriteString( "." );
}
for ( int j = 0 ; j < 2 ; j++ ) {
file->WriteBig( dictionary[i].imageSize[j] );
file->WriteBig( dictionary[i].imageAtlasOffset[j] );
}
for ( int j = 0 ; j < 4 ; j++ ) {
file->WriteBig( dictionary[i].channelScale[j] );
}
break;
}
case SWF_DICT_MORPH:
case SWF_DICT_SHAPE: {
idSWFShape * shape = dictionary[i].shape;
file->WriteBig( shape->startBounds.tl );
file->WriteBig( shape->startBounds.br );
file->WriteBig( shape->endBounds.tl );
file->WriteBig( shape->endBounds.br );
file->WriteBig( shape->fillDraws.Num() );
for ( int d = 0; d < shape->fillDraws.Num(); d++ ) {
idSWFShapeDrawFill & fillDraw = shape->fillDraws[d];
file->WriteBig( fillDraw.style.type );
file->WriteBig( fillDraw.style.subType );
file->Write( &fillDraw.style.startColor, 4 );
file->Write( &fillDraw.style.endColor, 4 );
file->WriteBigArray( (float *)&fillDraw.style.startMatrix, 6 );
file->WriteBigArray( (float *)&fillDraw.style.endMatrix, 6 );
file->WriteBig( fillDraw.style.gradient.numGradients );
for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) {
file->WriteBig( fillDraw.style.gradient.gradientRecords[g].startRatio );
file->WriteBig( fillDraw.style.gradient.gradientRecords[g].endRatio );
file->Write( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 );
file->Write( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 );
}
file->WriteBig( fillDraw.style.focalPoint );
file->WriteBig( fillDraw.style.bitmapID );
file->WriteBig( fillDraw.startVerts.Num() );
file->WriteBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() );
file->WriteBig( fillDraw.endVerts.Num() );
file->WriteBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() );
file->WriteBig( fillDraw.indices.Num() );
file->WriteBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() );
}
file->WriteBig( shape->lineDraws.Num() );
for ( int d = 0; d < shape->lineDraws.Num(); d++ ) {
idSWFShapeDrawLine & lineDraw = shape->lineDraws[d];
file->WriteBig( lineDraw.style.startWidth );
file->WriteBig( lineDraw.style.endWidth );
file->Write( &lineDraw.style.startColor, 4 );
file->Write( &lineDraw.style.endColor, 4 );
file->WriteBig( lineDraw.startVerts.Num() );
file->WriteBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() );
file->WriteBig( lineDraw.endVerts.Num() );
file->WriteBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() );
file->WriteBig( lineDraw.indices.Num() );
file->WriteBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() );
}
break;
}
case SWF_DICT_SPRITE: {
dictionary[i].sprite->Write( file );
break;
}
case SWF_DICT_FONT: {
idSWFFont * font = dictionary[i].font;
file->WriteString( font->fontID->GetName() );
file->WriteBig( font->ascent );
file->WriteBig( font->descent );
file->WriteBig( font->leading );
file->WriteBig( font->glyphs.Num() );
for ( int g = 0; g < font->glyphs.Num(); g++ ) {
file->WriteBig( font->glyphs[g].code );
file->WriteBig( font->glyphs[g].advance );
file->WriteBig( font->glyphs[g].verts.Num() );
file->WriteBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() );
file->WriteBig( font->glyphs[g].indices.Num() );
file->WriteBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() );
}
break;
}
case SWF_DICT_TEXT: {
idSWFText * text = dictionary[i].text;
file->WriteBig( text->bounds.tl );
file->WriteBig( text->bounds.br );
file->WriteBigArray( (float *)&text->matrix, 6 );
file->WriteBig( text->textRecords.Num() );
for ( int t = 0; t < text->textRecords.Num(); t++ ) {
idSWFTextRecord & textRecord = text->textRecords[t];
file->WriteBig( textRecord.fontID );
file->Write( &textRecord.color, 4 );
file->WriteBig( textRecord.xOffset );
file->WriteBig( textRecord.yOffset );
file->WriteBig( textRecord.textHeight );
file->WriteBig( textRecord.firstGlyph );
file->WriteBig( textRecord.numGlyphs );
}
file->WriteBig( text->glyphs.Num() );
for ( int g = 0; g < text->glyphs.Num(); g++ ) {
file->WriteBig( text->glyphs[g].index );
file->WriteBig( text->glyphs[g].advance );
}
break;
}
case SWF_DICT_EDITTEXT: {
idSWFEditText * edittext = dictionary[i].edittext;
file->WriteBig( edittext->bounds.tl );
file->WriteBig( edittext->bounds.br );
file->WriteBig( edittext->flags );
file->WriteBig( edittext->fontID );
file->WriteBig( edittext->fontHeight );
file->Write( &edittext->color, 4 );
file->WriteBig( edittext->maxLength );
file->WriteBig( edittext->align );
file->WriteBig( edittext->leftMargin );
file->WriteBig( edittext->rightMargin );
file->WriteBig( edittext->indent );
file->WriteBig( edittext->leading );
file->WriteString( edittext->variable );
file->WriteString( edittext->initialText );
break;
}
}
}
}

709
neo/swf/SWF_Main.cpp Normal file
View File

@@ -0,0 +1,709 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "../renderer/image.h"
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
idCVar swf_loadBinary( "swf_loadBinary", "1", CVAR_INTEGER, "used to set whether to load binary swf from generated" );
int idSWF::mouseX = -1;
int idSWF::mouseY = -1;
bool idSWF::isMouseInClientArea = false;
extern idCVar in_useJoystick;
/*
===================
idSWF::idSWF
===================
*/
idSWF::idSWF( const char * filename_, idSoundWorld * soundWorld_ ) {
atlasMaterial = NULL;
swfScale = 1.0f;
scaleToVirtual.Set( 1.0f, 1.0f );
random.SetSeed( Sys_Milliseconds() );
guiSolid = declManager->FindMaterial( "guiSolid" );
guiCursor_arrow = declManager->FindMaterial( "ui/assets/guicursor_arrow" );
guiCursor_hand = declManager->FindMaterial( "ui/assets/guicursor_hand" );
white = declManager->FindMaterial( "_white" );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY1>", "guis/assets/hud/controller/xb360/a", "guis/assets/hud/controller/ps3/cross", 37, 37, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY2>", "guis/assets/hud/controller/xb360/b", "guis/assets/hud/controller/ps3/circle", 37, 37, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY3>", "guis/assets/hud/controller/xb360/x", "guis/assets/hud/controller/ps3/square", 37, 37, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY4>", "guis/assets/hud/controller/xb360/y", "guis/assets/hud/controller/ps3/triangle", 37, 37, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY_TRIGGER2>", "guis/assets/hud/controller/xb360/rt", "guis/assets/hud/controller/ps3/r2", 64, 52, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY_TRIGGER1>", "guis/assets/hud/controller/xb360/lt", "guis/assets/hud/controller/ps3/l2", 64, 52, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY5>", "guis/assets/hud/controller/xb360/lb", "guis/assets/hud/controller/ps3/l1", 52, 32, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<JOY6>", "guis/assets/hud/controller/xb360/rb", "guis/assets/hud/controller/ps3/r1", 52, 32, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<MOUSE1>", "guis/assets/hud/controller/mouse1", "", 64, 52, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<MOUSE2>", "guis/assets/hud/controller/mouse2", "", 64, 52, 0 ) );
tooltipButtonImage.Append( keyButtonImages_t( "<MOUSE3>", "guis/assets/hud/controller/mouse3", "", 64, 52, 0 ) );
for ( int index = 0; index < tooltipButtonImage.Num(); index++ ) {
if ( ( tooltipButtonImage[index].xbImage != NULL ) && ( tooltipButtonImage[index].xbImage[0] != '\0' ) ) {
declManager->FindMaterial( tooltipButtonImage[index].xbImage );
}
if ( ( tooltipButtonImage[index].psImage != NULL ) && ( tooltipButtonImage[index].psImage[0] != '\0' ) ) {
declManager->FindMaterial( tooltipButtonImage[index].psImage );
}
}
frameWidth = 0;
frameHeight = 0;
frameRate = 0;
lastRenderTime = 0;
isActive = false;
inhibitControl = false;
useInhibtControl = true;
crop = false;
blackbars = false;
paused = false;
hasHitObject = false;
useMouse = true;
mouseEnabled = false;
renderBorder = 0;
mouseObject = NULL;
hoverObject = NULL;
soundWorld = NULL;
forceNonPCPlatform = false;
if ( idStr::Cmpn( filename_, "swf/", 4 ) != 0 ) {
// if it doesn't already have swf/ in front of it, add it
filename = "swf/";
filename += filename_;
} else {
filename = filename_;
}
filename.ToLower();
filename.BackSlashesToSlashes();
filename.SetFileExtension( ".swf" );
timestamp = fileSystem->GetTimestamp( filename );
mainsprite = new (TAG_SWF) idSWFSprite( this );
mainspriteInstance = NULL;
idStr binaryFileName = "generated/";
binaryFileName += filename;
binaryFileName.SetFileExtension( ".bswf" );
if ( swf_loadBinary.GetBool() ) {
ID_TIME_T sourceTime = fileSystem->GetTimestamp( filename );
if ( !LoadBinary( binaryFileName, sourceTime ) ) {
if ( LoadSWF( filename ) ) {
WriteBinary( binaryFileName );
}
}
} else {
LoadSWF( filename );
}
idStr atlasFileName = binaryFileName;
atlasFileName.SetFileExtension( ".tga" );
atlasMaterial = declManager->FindMaterial( atlasFileName );
globals = idSWFScriptObject::Alloc();
globals->Set( "_global", globals );
globals->Set( "Object", &scriptFunction_Object );
mainspriteInstance = spriteInstanceAllocator.Alloc();
mainspriteInstance->Init( mainsprite, NULL, 0 );
shortcutKeys = idSWFScriptObject::Alloc();
scriptFunction_shortcutKeys_clear.Bind( this );
scriptFunction_shortcutKeys_clear.Call( shortcutKeys, idSWFParmList() );
globals->Set( "shortcutKeys", shortcutKeys );
globals->Set( "deactivate", scriptFunction_deactivate.Bind( this ) );
globals->Set( "inhibitControl", scriptFunction_inhibitControl.Bind( this ) );
globals->Set( "useInhibit", scriptFunction_useInhibit.Bind( this ) );
globals->Set( "precacheSound", scriptFunction_precacheSound.Bind( this ) );
globals->Set( "playSound", scriptFunction_playSound.Bind( this ) );
globals->Set( "stopSounds",scriptFunction_stopSounds.Bind( this ) );
globals->Set( "getPlatform", scriptFunction_getPlatform.Bind( this ) );
globals->Set( "getTruePlatform", scriptFunction_getTruePlatform.Bind( this ) );
globals->Set( "getLocalString", scriptFunction_getLocalString.Bind( this ) );
globals->Set( "swapPS3Buttons", scriptFunction_swapPS3Buttons.Bind( this ) );
globals->Set( "_root", mainspriteInstance->scriptObject );
globals->Set( "strReplace", scriptFunction_strReplace.Bind( this ) );
globals->Set( "getCVarInteger", scriptFunction_getCVarInteger.Bind( this ) );
globals->Set( "setCVarInteger", scriptFunction_setCVarInteger.Bind( this ) );
globals->Set( "acos", scriptFunction_acos.Bind( this ) );
globals->Set( "cos", scriptFunction_cos.Bind( this ) );
globals->Set( "sin", scriptFunction_sin.Bind( this ) );
globals->Set( "round", scriptFunction_round.Bind( this ) );
globals->Set( "pow", scriptFunction_pow.Bind( this ) );
globals->Set( "sqrt", scriptFunction_sqrt.Bind( this ) );
globals->Set( "abs", scriptFunction_abs.Bind( this ) );
globals->Set( "rand", scriptFunction_rand.Bind( this ) );
globals->Set( "floor", scriptFunction_floor.Bind( this ) );
globals->Set( "ceil", scriptFunction_ceil.Bind( this ) );
globals->Set( "toUpper", scriptFunction_toUpper.Bind( this ) );
globals->SetNative( "platform", swfScriptVar_platform.Bind( &scriptFunction_getPlatform ) );
globals->SetNative( "blackbars", swfScriptVar_blackbars.Bind( this ) );
globals->SetNative( "cropToHeight", swfScriptVar_crop.Bind( this ) );
globals->SetNative( "cropToFit", swfScriptVar_crop.Bind( this ) );
globals->SetNative( "crop", swfScriptVar_crop.Bind( this ) );
// Do this to touch any external references (like sounds)
// But disable script warnings because many globals won't have been created yet
extern idCVar swf_debug;
int debug = swf_debug.GetInteger();
swf_debug.SetInteger( 0 );
mainspriteInstance->Run();
mainspriteInstance->RunActions();
mainspriteInstance->RunTo( 0 );
swf_debug.SetInteger( debug );
if ( mouseX == -1 ) {
mouseX = ( frameWidth / 2 );
}
if ( mouseY == -1 ) {
mouseY = ( frameHeight / 2 );
}
soundWorld = soundWorld_;
}
/*
===================
idSWF::~idSWF
===================
*/
idSWF::~idSWF() {
spriteInstanceAllocator.Free( mainspriteInstance );
delete mainsprite;
for ( int i = 0 ; i < dictionary.Num() ; i++ ) {
if ( dictionary[i].sprite ) {
delete dictionary[i].sprite;
dictionary[i].sprite = NULL;
}
if ( dictionary[i].shape ) {
delete dictionary[i].shape;
dictionary[i].shape = NULL;
}
if ( dictionary[i].font ) {
delete dictionary[i].font;
dictionary[i].font = NULL;
}
if ( dictionary[i].text ) {
delete dictionary[i].text;
dictionary[i].text = NULL;
}
if ( dictionary[i].edittext ) {
delete dictionary[i].edittext;
dictionary[i].edittext = NULL;
}
}
globals->Clear();
tooltipButtonImage.Clear();
globals->Release();
shortcutKeys->Clear();
shortcutKeys->Release();
}
/*
===================
idSWF::Activate
when a SWF is deactivated, it rewinds the timeline back to the start
===================
*/
void idSWF::Activate( bool b ) {
if ( !isActive && b ) {
inhibitControl = false;
lastRenderTime = Sys_Milliseconds();
mainspriteInstance->FreeDisplayList();
mainspriteInstance->Play();
mainspriteInstance->Run();
mainspriteInstance->RunActions();
}
isActive = b;
}
/*
===================
idSWF::InhibitControl
===================
*/
bool idSWF::InhibitControl() {
if ( !IsLoaded() || !IsActive() ) {
return false;
}
return ( inhibitControl && useInhibtControl );
}
/*
===================
idSWF::PlaySound
===================
*/
int idSWF::PlaySound( const char * sound, int channel, bool blocking ) {
if ( !IsActive() ) {
return -1;
}
if ( soundWorld != NULL ) {
return soundWorld->PlayShaderDirectly( sound, channel );
} else {
idLib::Warning( "No playing sound world on soundSystem in swf play sound!" );
return -1;
}
}
/*
===================
idSWF::PlaySound
===================
*/
void idSWF::StopSound( int channel ) {
if ( soundWorld != NULL ) {
soundWorld->PlayShaderDirectly( NULL, channel );
} else {
idLib::Warning( "No playing sound world on soundSystem in swf play sound!" );
}
}
/*
===================
idSWF::idSWFScriptFunction_inhibitControl::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_inhibitControl::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
pThis->inhibitControl = parms[0].ToBool();
return idSWFScriptVar();
}
/*
===================
idSWF::idSWFScriptFunction_inhibitControl::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_useInhibit::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
pThis->useInhibtControl = parms[0].ToBool();
return idSWFScriptVar();
}
/*
===================
idSWF::idSWFScriptFunction_deactivate::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_deactivate::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
pThis->Activate( false );
return idSWFScriptVar();
}
/*
===================
idSWF::idSWFScriptFunction_precacheSound::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_precacheSound::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
const idSoundShader * soundShader = declManager->FindSound( parms[0].ToString(), true );
return soundShader->GetName();
}
/*
===================
idSWF::idSWFScriptFunction_playSound::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_playSound::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
int channel = SCHANNEL_ANY;
// specific channel passed in
if ( parms.Num() > 1 ) {
channel = parms[1].ToInteger();
}
pThis->PlaySound( parms[0].ToString(), channel );
return idSWFScriptVar();
}
/*
===================
idSWF::idSWFScriptFunction_stopSounds::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_stopSounds::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
int channel = SCHANNEL_ANY;
if ( parms.Num() == 1 ) {
channel = parms[0].ToInteger();
}
pThis->StopSound( channel );
return idSWFScriptVar();
}
/*
========================
idSWFScriptFunction_GetPlatform::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_getPlatform::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
return pThis->GetPlatform();
}
/*
========================
idSWFScriptFunction_GetPlatform::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_getTruePlatform::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
return 2;
}
/*
========================
idSWFScriptFunction_GetPlatform::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_strReplace::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 3 ) {
return "";
}
idStr str = parms[0].ToString();
idStr repString = parms[1].ToString();
idStr val = parms[2].ToString();
str.Replace( repString, val );
return str;
}
/*
========================
idSWFScriptFunction_GetPlatform::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_getLocalString::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() == 0 ) {
return idSWFScriptVar();
}
idStr val = idLocalization::GetString( parms[0].ToString() );
return val;
}
/*
========================
idSWF::UseCircleForAccept
========================
*/
bool idSWF::UseCircleForAccept() {
return false;
}
/*
========================
idSWF::GetPlatform
========================
*/
int idSWF::GetPlatform() {
if ( in_useJoystick.GetBool() || forceNonPCPlatform ) {
forceNonPCPlatform = false;
return 0;
}
return 2;
}
/*
========================
idSWFScriptFunction_swapPS3Buttons::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_swapPS3Buttons::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
return pThis->UseCircleForAccept();
}
/*
========================
idSWFScriptFunction_getCVarInteger::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_getCVarInteger::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
return cvarSystem->GetCVarInteger( parms[0].ToString() );
}
/*
========================
idSWFScriptFunction_setCVarInteger::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_setCVarInteger::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
cvarSystem->SetCVarInteger( parms[0].ToString(), parms[1].ToInteger() );
return idSWFScriptVar();
}
/*
===================
idSWF::idSWFScriptFunction_acos::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_acos::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
return idMath::ACos( parms[0].ToFloat() );
}
/*
===================
idSWF::idSWFScriptFunction_cos::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_cos::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
return idMath::Cos( parms[0].ToFloat() );
}
/*
===================
idSWF::idSWFScriptFunction_sin::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_sin::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
return ( idMath::Sin( parms[0].ToFloat() ) );
}
/*
===================
idSWF::idSWFScriptFunction_round::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_round::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
int value = idMath::Ftoi( parms[0].ToFloat() + 0.5f );
return value;
}
/*
===================
idSWF::idSWFScriptFunction_pow::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_pow::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 2 ) {
return idSWFScriptVar();
}
float value = parms[0].ToFloat();
float power = parms[1].ToFloat();
return ( idMath::Pow( value, power ) );
}
/*
===================
idSWF::idSWFScriptFunction_pow::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_sqrt::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
float value = parms[0].ToFloat();
return ( idMath::Sqrt( value ) );
}
/*
===================
idSWF::idSWFScriptFunction_abs::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_abs::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 ) {
return idSWFScriptVar();
}
float value = idMath::Fabs( parms[0].ToFloat() );
return value;
}
/*
===================
idSWF::idSWFScriptFunction_rand::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_rand::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
float min = 0.0f;
float max = 1.0f;
switch ( parms.Num() ) {
case 0:
break;
case 1:
max = parms[0].ToFloat();
break;
default:
min = parms[0].ToFloat();
max = parms[1].ToFloat();
break;
}
return min + pThis->GetRandom().RandomFloat() * ( max - min );
}
/*
========================
idSWFScriptFunction_floor::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_floor::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 || !parms[0].IsNumeric() ) {
idLib::Warning( "Invalid parameters specified for floor" );
return idSWFScriptVar();
}
float num = parms[0].ToFloat();
return idSWFScriptVar( idMath::Floor( num ) );
}
/*
========================
idSWFScriptFunction_ceil::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_ceil::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 || !parms[0].IsNumeric() ) {
idLib::Warning( "Invalid parameters specified for ceil" );
return idSWFScriptVar();
}
float num = parms[0].ToFloat();
return idSWFScriptVar( idMath::Ceil( num ) );
}
/*
========================
idSWFScriptFunction_toUpper::Call
========================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_toUpper::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
if ( parms.Num() != 1 || !parms[0].IsString() ) {
idLib::Warning( "Invalid parameters specified for toUpper" );
return idSWFScriptVar();
}
idStr val = idLocalization::GetString( parms[0].ToString() );
val.ToUpper();
return val;
}
/*
===================
idSWF::idSWFScriptFunction_shortcutKeys_clear::Call
===================
*/
idSWFScriptVar idSWF::idSWFScriptFunction_shortcutKeys_clear::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
idSWFScriptObject * object = pThis->shortcutKeys;
object->Clear();
object->Set( "clear", this );
object->Set( "JOY1", "ENTER" );
object->Set( "JOY2", "BACKSPACE" );
object->Set( "JOY3", "START" );
object->Set( "JOY5", "LB" );
object->Set( "JOY6", "RB" );
object->Set( "JOY9", "START" );
object->Set( "JOY10", "BACKSPACE" );
object->Set( "JOY_DPAD_UP", "UP" );
object->Set( "JOY_DPAD_DOWN", "DOWN" );
object->Set( "JOY_DPAD_LEFT", "LEFT" );
object->Set( "JOY_DPAD_RIGHT", "RIGHT" );
object->Set( "JOY_STICK1_UP", "STICK1_UP" );
object->Set( "JOY_STICK1_DOWN", "STICK1_DOWN" );
object->Set( "JOY_STICK1_LEFT", "STICK1_LEFT" );
object->Set( "JOY_STICK1_RIGHT", "STICK1_RIGHT" );
object->Set( "JOY_STICK2_UP", "STICK2_UP" );
object->Set( "JOY_STICK2_DOWN", "STICK2_DOWN" );
object->Set( "JOY_STICK2_LEFT", "STICK2_LEFT" );
object->Set( "JOY_STICK2_RIGHT", "STICK2_RIGHT" );
object->Set( "KP_ENTER", "ENTER" );
object->Set( "MWHEELDOWN", "MWHEEL_DOWN" );
object->Set( "MWHEELUP", "MWHEEL_UP" );
object->Set( "K_TAB", "TAB" );
// FIXME: I'm an RTARD and didn't realize the keys all have "ARROW" after them
object->Set( "LEFTARROW", "LEFT" );
object->Set( "RIGHTARROW", "RIGHT" );
object->Set( "UPARROW", "UP" );
object->Set( "DOWNARROW", "DOWN" );
return idSWFScriptVar();
}
idSWFScriptVar idSWF::idSWFScriptNativeVar_blackbars::Get( idSWFScriptObject * object ) {
return pThis->blackbars;
}
void idSWF::idSWFScriptNativeVar_blackbars::Set( idSWFScriptObject * object, const idSWFScriptVar & value ) {
pThis->blackbars = value.ToBool();
}
idSWFScriptVar idSWF::idSWFScriptNativeVar_crop::Get( idSWFScriptObject * object ) {
return pThis->crop;
}
void idSWF::idSWFScriptNativeVar_crop::Set( idSWFScriptObject * object, const idSWFScriptVar & value ) {
pThis->crop = value.ToBool();
}

215
neo/swf/SWF_Names.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
========================
idSWF::GetTagName
========================
*/
const char * idSWF::GetTagName( swfTag_t tag ) {
#define SWF_TAG_NAME( x ) case Tag_##x: return #x;
switch ( tag ) {
SWF_TAG_NAME( End );
SWF_TAG_NAME( ShowFrame );
SWF_TAG_NAME( DefineShape );
SWF_TAG_NAME( PlaceObject );
SWF_TAG_NAME( RemoveObject );
SWF_TAG_NAME( DefineBits );
SWF_TAG_NAME( DefineButton );
SWF_TAG_NAME( JPEGTables );
SWF_TAG_NAME( SetBackgroundColor );
SWF_TAG_NAME( DefineFont );
SWF_TAG_NAME( DefineText );
SWF_TAG_NAME( DoAction );
SWF_TAG_NAME( DefineFontInfo );
SWF_TAG_NAME( DefineSound );
SWF_TAG_NAME( StartSound );
SWF_TAG_NAME( DefineButtonSound );
SWF_TAG_NAME( SoundStreamHead );
SWF_TAG_NAME( SoundStreamBlock );
SWF_TAG_NAME( DefineBitsLossless );
SWF_TAG_NAME( DefineBitsJPEG2 );
SWF_TAG_NAME( DefineShape2 );
SWF_TAG_NAME( DefineButtonCxform );
SWF_TAG_NAME( Protect );
SWF_TAG_NAME( PlaceObject2 );
SWF_TAG_NAME( RemoveObject2 );
SWF_TAG_NAME( DefineShape3 );
SWF_TAG_NAME( DefineText2 );
SWF_TAG_NAME( DefineButton2 );
SWF_TAG_NAME( DefineBitsJPEG3 );
SWF_TAG_NAME( DefineBitsLossless2 );
SWF_TAG_NAME( DefineEditText );
SWF_TAG_NAME( DefineSprite );
SWF_TAG_NAME( FrameLabel );
SWF_TAG_NAME( SoundStreamHead2 );
SWF_TAG_NAME( DefineMorphShape );
SWF_TAG_NAME( DefineFont2 );
SWF_TAG_NAME( ExportAssets );
SWF_TAG_NAME( ImportAssets );
SWF_TAG_NAME( EnableDebugger );
SWF_TAG_NAME( DoInitAction );
SWF_TAG_NAME( DefineVideoStream );
SWF_TAG_NAME( VideoFrame );
SWF_TAG_NAME( DefineFontInfo2 );
SWF_TAG_NAME( EnableDebugger2 );
SWF_TAG_NAME( ScriptLimits );
SWF_TAG_NAME( SetTabIndex );
SWF_TAG_NAME( FileAttributes );
SWF_TAG_NAME( PlaceObject3 );
SWF_TAG_NAME( ImportAssets2 );
SWF_TAG_NAME( DefineFontAlignZones );
SWF_TAG_NAME( CSMTextSettings );
SWF_TAG_NAME( DefineFont3 );
SWF_TAG_NAME( SymbolClass );
SWF_TAG_NAME( Metadata );
SWF_TAG_NAME( DefineScalingGrid );
SWF_TAG_NAME( DoABC );
SWF_TAG_NAME( DefineShape4 );
SWF_TAG_NAME( DefineMorphShape2 );
SWF_TAG_NAME( DefineSceneAndFrameLabelData );
SWF_TAG_NAME( DefineBinaryData );
SWF_TAG_NAME( DefineFontName );
SWF_TAG_NAME( StartSound2 );
default: return "????";
}
}
/*
========================
idSWF::GetActionName
========================
*/
const char * idSWF::GetActionName( swfAction_t action ) {
#define SWF_ACTION_NAME( x ) case Action_##x: return #x;
switch ( action ) {
SWF_ACTION_NAME( NextFrame );
SWF_ACTION_NAME( PrevFrame );
SWF_ACTION_NAME( Play );
SWF_ACTION_NAME( Stop );
SWF_ACTION_NAME( ToggleQuality );
SWF_ACTION_NAME( StopSounds );
SWF_ACTION_NAME( GotoFrame );
SWF_ACTION_NAME( GetURL );
SWF_ACTION_NAME( WaitForFrame );
SWF_ACTION_NAME( SetTarget );
SWF_ACTION_NAME( GoToLabel );
SWF_ACTION_NAME( Add );
SWF_ACTION_NAME( Subtract );
SWF_ACTION_NAME( Multiply );
SWF_ACTION_NAME( Divide );
SWF_ACTION_NAME( Equals );
SWF_ACTION_NAME( Less );
SWF_ACTION_NAME( And );
SWF_ACTION_NAME( Or );
SWF_ACTION_NAME( Not );
SWF_ACTION_NAME( StringEquals );
SWF_ACTION_NAME( StringLength );
SWF_ACTION_NAME( StringExtract );
SWF_ACTION_NAME( Pop );
SWF_ACTION_NAME( ToInteger );
SWF_ACTION_NAME( GetVariable );
SWF_ACTION_NAME( SetVariable );
SWF_ACTION_NAME( SetTarget2 );
SWF_ACTION_NAME( StringAdd );
SWF_ACTION_NAME( GetProperty );
SWF_ACTION_NAME( SetProperty );
SWF_ACTION_NAME( CloneSprite );
SWF_ACTION_NAME( RemoveSprite );
SWF_ACTION_NAME( Trace );
SWF_ACTION_NAME( StartDrag );
SWF_ACTION_NAME( EndDrag );
SWF_ACTION_NAME( StringLess );
SWF_ACTION_NAME( RandomNumber );
SWF_ACTION_NAME( MBStringLength );
SWF_ACTION_NAME( CharToAscii );
SWF_ACTION_NAME( AsciiToChar );
SWF_ACTION_NAME( GetTime );
SWF_ACTION_NAME( MBStringExtract );
SWF_ACTION_NAME( MBCharToAscii );
SWF_ACTION_NAME( MBAsciiToChar );
SWF_ACTION_NAME( WaitForFrame2 );
SWF_ACTION_NAME( Push );
SWF_ACTION_NAME( Jump );
SWF_ACTION_NAME( GetURL2 );
SWF_ACTION_NAME( If );
SWF_ACTION_NAME( Call );
SWF_ACTION_NAME( GotoFrame2 );
SWF_ACTION_NAME( Delete );
SWF_ACTION_NAME( Delete2 );
SWF_ACTION_NAME( DefineLocal );
SWF_ACTION_NAME( CallFunction );
SWF_ACTION_NAME( Return );
SWF_ACTION_NAME( Modulo );
SWF_ACTION_NAME( NewObject );
SWF_ACTION_NAME( DefineLocal2 );
SWF_ACTION_NAME( InitArray );
SWF_ACTION_NAME( InitObject );
SWF_ACTION_NAME( TypeOf );
SWF_ACTION_NAME( TargetPath );
SWF_ACTION_NAME( Enumerate );
SWF_ACTION_NAME( Add2 );
SWF_ACTION_NAME( Less2 );
SWF_ACTION_NAME( Equals2 );
SWF_ACTION_NAME( ToNumber );
SWF_ACTION_NAME( ToString );
SWF_ACTION_NAME( PushDuplicate );
SWF_ACTION_NAME( StackSwap );
SWF_ACTION_NAME( GetMember );
SWF_ACTION_NAME( SetMember );
SWF_ACTION_NAME( Increment );
SWF_ACTION_NAME( Decrement );
SWF_ACTION_NAME( CallMethod );
SWF_ACTION_NAME( NewMethod );
SWF_ACTION_NAME( BitAnd );
SWF_ACTION_NAME( BitOr );
SWF_ACTION_NAME( BitXor );
SWF_ACTION_NAME( BitLShift );
SWF_ACTION_NAME( BitRShift );
SWF_ACTION_NAME( BitURShift );
SWF_ACTION_NAME( StoreRegister );
SWF_ACTION_NAME( ConstantPool );
SWF_ACTION_NAME( With );
SWF_ACTION_NAME( DefineFunction );
SWF_ACTION_NAME( InstanceOf );
SWF_ACTION_NAME( Enumerate2 );
SWF_ACTION_NAME( StrictEquals );
SWF_ACTION_NAME( Greater );
SWF_ACTION_NAME( StringGreater );
SWF_ACTION_NAME( Extends );
SWF_ACTION_NAME( CastOp );
SWF_ACTION_NAME( ImplementsOp );
SWF_ACTION_NAME( Throw );
SWF_ACTION_NAME( Try );
SWF_ACTION_NAME( DefineFunction2 );
default: return "???";
}
}

85
neo/swf/SWF_ParmList.cpp Normal file
View File

@@ -0,0 +1,85 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
void idSWFParmList::Append( const idSWFScriptVar & other ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
*var = other;
}
}
void idSWFParmList::Append( idSWFScriptObject * o ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetObject( o );
}
}
void idSWFParmList::Append( idSWFScriptFunction * f ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetFunction( f );
}
}
void idSWFParmList::Append( const char * s ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetString( s );
}
}
void idSWFParmList::Append( const idStr & s ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetString( s );
}
}
void idSWFParmList::Append( idSWFScriptString * s ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetString( s );
}
}
void idSWFParmList::Append( const float f ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetFloat( f );
}
}
void idSWFParmList::Append( const int32 i ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetInteger( i );
}
}
void idSWFParmList::Append( const bool b ) {
idSWFScriptVar * var = Alloc();
if ( var != NULL ) {
var->SetBool( b );
}
}

60
neo/swf/SWF_ParmList.h Normal file
View File

@@ -0,0 +1,60 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_PARMLIST_H__
#define __SWF_PARMLIST_H__
// static list for script parameters
static const int SWF_MAX_PARMS = 16;
/*
================================================
idSWFParmList
A static list for script parameters that reduces the number of SWF allocations dramatically.
================================================
*/
class idSWFParmList : public idStaticList< idSWFScriptVar, SWF_MAX_PARMS > {
public:
idSWFParmList() {
}
explicit idSWFParmList( const int num_ ) {
SetNum( num_ );
}
void Append( const idSWFScriptVar & other );
void Append( idSWFScriptObject * o );
void Append( idSWFScriptFunction * f );
void Append( const char * s );
void Append( const idStr & s );
void Append( idSWFScriptString * s );
void Append( const float f );
void Append( const int32 i );
void Append( const bool b );
};
#endif // __SWF_PARMLIST_H__

231
neo/swf/SWF_PlaceObject.cpp Normal file
View File

@@ -0,0 +1,231 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
int c_PlaceObject2;
int c_PlaceObject3;
#define PlaceFlagHasClipActions BIT( 7 )
#define PlaceFlagHasClipDepth BIT( 6 )
#define PlaceFlagHasName BIT( 5 )
#define PlaceFlagHasRatio BIT( 4 )
#define PlaceFlagHasColorTransform BIT( 3 )
#define PlaceFlagHasMatrix BIT( 2 )
#define PlaceFlagHasCharacter BIT( 1 )
#define PlaceFlagMove BIT( 0 )
#define PlaceFlagPad0 BIT( 7 )
#define PlaceFlagPad1 BIT( 6 )
#define PlaceFlagPad2 BIT( 5 )
#define PlaceFlagHasImage BIT( 4 )
#define PlaceFlagHasClassName BIT( 3 )
#define PlaceFlagCacheAsBitmap BIT( 2 )
#define PlaceFlagHasBlendMode BIT( 1 )
#define PlaceFlagHasFilterList BIT( 0 )
/*
========================
idSWFSpriteInstance::PlaceObject2
========================
*/
void idSWFSpriteInstance::PlaceObject2( idSWFBitStream & bitstream ) {
c_PlaceObject2++;
uint64 flags = bitstream.ReadU8();
int depth = bitstream.ReadU16();
int characterID = -1;
if ( ( flags & PlaceFlagHasCharacter ) != 0 ) {
characterID = bitstream.ReadU16();
}
swfDisplayEntry_t * display = NULL;
if ( ( flags & PlaceFlagMove ) != 0 ) {
// modify an existing entry
display = FindDisplayEntry( depth );
if ( display == NULL ) {
idLib::Warning( "PlaceObject2: trying to modify entry %d, which doesn't exist", depth );
return;
}
if ( characterID >= 0 ) {
// We are very picky about what kind of objects can change characters
// Shapes can become other shapes, but sprites can never change
if ( display->spriteInstance || display->textInstance ) {
idLib::Warning( "PlaceObject2: Trying to change the character of a sprite after it's been created" );
return;
}
idSWFDictionaryEntry * dictEntry = sprite->swf->FindDictionaryEntry( characterID );
if ( dictEntry != NULL ) {
if ( dictEntry->type == SWF_DICT_SPRITE || dictEntry->type == SWF_DICT_EDITTEXT ) {
idLib::Warning( "PlaceObject2: Trying to change the character of a shape to a sprite" );
return;
}
}
display->characterID = characterID;
}
} else {
if ( characterID < 0 ) {
idLib::Warning( "PlaceObject2: Trying to create a new object without a character" );
return;
}
// create a new entry
display = AddDisplayEntry( depth, characterID );
if ( display == NULL ) {
idLib::Warning( "PlaceObject2: trying to create a new entry at %d, but an item already exists there", depth );
return;
}
}
if ( ( flags & PlaceFlagHasMatrix ) != 0 ) {
bitstream.ReadMatrix( display->matrix );
}
if ( ( flags & PlaceFlagHasColorTransform ) != 0 ) {
bitstream.ReadColorXFormRGBA( display->cxf );
}
if ( ( flags & PlaceFlagHasRatio ) != 0 ) {
display->ratio = bitstream.ReadU16() * ( 1.0f / 65535.0f );
}
if ( ( flags & PlaceFlagHasName ) != 0 ) {
idStr name = bitstream.ReadString();
if ( display->spriteInstance ) {
display->spriteInstance->name = name;
scriptObject->Set( name, display->spriteInstance->GetScriptObject() );
} else if ( display->textInstance ) {
scriptObject->Set( name, display->textInstance->GetScriptObject() );
}
}
if ( ( flags & PlaceFlagHasClipDepth ) != 0 ) {
display->clipDepth = bitstream.ReadU16();
}
if ( ( flags & PlaceFlagHasClipActions ) != 0 ) {
// FIXME: clip actions
}
}
/*
========================
idSWFSpriteInstance::PlaceObject3
========================
*/
void idSWFSpriteInstance::PlaceObject3( idSWFBitStream & bitstream ) {
c_PlaceObject3++;
uint64 flags1 = bitstream.ReadU8();
uint64 flags2 = bitstream.ReadU8();
uint16 depth = bitstream.ReadU16();
if ( ( flags2 & PlaceFlagHasClassName ) != 0 || ( ( ( flags2 & PlaceFlagHasImage ) != 0 ) && ( ( flags1 & PlaceFlagHasCharacter ) != 0 ) ) ) {
bitstream.ReadString(); // ignored
}
int characterID = -1;
if ( ( flags1 & PlaceFlagHasCharacter ) != 0 ) {
characterID = bitstream.ReadU16();
}
swfDisplayEntry_t * display = NULL;
if ( ( flags1 & PlaceFlagMove ) != 0 ) {
// modify an existing entry
display = FindDisplayEntry( depth );
if ( display == NULL ) {
idLib::Warning( "PlaceObject3: trying to modify entry %d, which doesn't exist", depth );
return;
}
if ( characterID >= 0 ) {
// We are very picky about what kind of objects can change characters
// Shapes can become other shapes, but sprites can never change
if ( display->spriteInstance || display->textInstance ) {
idLib::Warning( "PlaceObject3: Trying to change the character of a sprite after it's been created" );
return;
}
idSWFDictionaryEntry * dictEntry = sprite->swf->FindDictionaryEntry( characterID );
if ( dictEntry != NULL ) {
if ( dictEntry->type == SWF_DICT_SPRITE || dictEntry->type == SWF_DICT_EDITTEXT ) {
idLib::Warning( "PlaceObject3: Trying to change the character of a shape to a sprite" );
return;
}
}
display->characterID = characterID;
}
} else {
if ( characterID < 0 ) {
idLib::Warning( "PlaceObject3: Trying to create a new object without a character" );
return;
}
// create a new entry
display = AddDisplayEntry( depth, characterID );
if ( display == NULL ) {
idLib::Warning( "PlaceObject3: trying to create a new entry at %d, but an item already exists there", depth );
return;
}
}
if ( ( flags1 & PlaceFlagHasMatrix ) != 0 ) {
bitstream.ReadMatrix( display->matrix );
}
if ( ( flags1 & PlaceFlagHasColorTransform ) != 0 ) {
bitstream.ReadColorXFormRGBA( display->cxf );
}
if ( ( flags1 & PlaceFlagHasRatio ) != 0 ) {
display->ratio = bitstream.ReadU16() * ( 1.0f / 65535.0f );
}
if ( ( flags1 & PlaceFlagHasName ) != 0 ) {
idStr name = bitstream.ReadString();
if ( display->spriteInstance ) {
display->spriteInstance->name = name;
scriptObject->Set( name, display->spriteInstance->GetScriptObject() );
} else if ( display->textInstance ) {
scriptObject->Set( name, display->textInstance->GetScriptObject() );
}
}
if ( ( flags1 & PlaceFlagHasClipDepth ) != 0 ) {
display->clipDepth = bitstream.ReadU16();
}
if ( ( flags2 & PlaceFlagHasFilterList ) != 0 ) {
// we don't support filters and because the filter list is variable length we
// can't support anything after the filter list either (blend modes and clip actions)
idLib::Warning( "PlaceObject3: has filters" );
return;
}
if ( ( flags2 & PlaceFlagHasBlendMode ) != 0 ) {
display->blendMode = bitstream.ReadU8();
}
if ( ( flags1 & PlaceFlagHasClipActions ) != 0 ) {
// FIXME:
}
}
/*
========================
idSWFSpriteInstance::RemoveObject2
========================
*/
void idSWFSpriteInstance::RemoveObject2( idSWFBitStream & bitstream ) {
RemoveDisplayEntry( bitstream.ReadU16() );
}

1536
neo/swf/SWF_Render.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SCRIPTFUNCTION_H__
#define __SWF_SCRIPTFUNCTION_H__
/*
========================
Interface for calling functions from script
========================
*/
class idSWFScriptFunction {
public:
virtual ~idSWFScriptFunction() {};
virtual idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ){ return idSWFScriptVar(); }; // this should never be hit
virtual void AddRef(){};
virtual void Release(){};
virtual idSWFScriptObject *GetPrototype() { return NULL; }
virtual void SetPrototype( idSWFScriptObject * _object ) { }
};
/*
========================
Interface for calling functions from script, implemented statically
========================
*/
class idSWFScriptFunction_Static : public idSWFScriptFunction {
public:
idSWFScriptFunction_Static() { }
virtual void AddRef() { }
virtual void Release() { }
};
/*
========================
Interface for calling functions from script, implemented natively on a nested class object
========================
*/
template< typename T >
class idSWFScriptFunction_Nested : public idSWFScriptFunction {
protected:
T * pThis;
public:
idSWFScriptFunction_Nested() : pThis( NULL ) { }
idSWFScriptFunction * Bind( T * _pThis ) { pThis = _pThis; return this; }
virtual void AddRef() { }
virtual void Release() { }
};
/*
========================
Interface for calling functions from script, with reference counting
NOTE: The ref count starts at 0 here because it assumes you do an AddRef on the allocated
object. The proper way is to start it at 1 and force the caller to Release, but that's
really kind of a pain in the ass. It was made to be used like this:
object->Set( "myFunction", new idSWFScriptFunction_MyFunction() );
========================
*/
class idSWFScriptFunction_RefCounted : public idSWFScriptFunction {
public:
idSWFScriptFunction_RefCounted() : refCount( 0 ) { }
void AddRef() { refCount++; }
void Release() { if ( --refCount <= 0 ) { delete this; } }
private:
int refCount;
};
/*
========================
Action Scripts can define a pool of constants then push values from that pool
The documentation isn't very clear on the scope of these things, but from what
I've gathered by testing, pool is per-function and copied into the function
whenever that function is declared.
========================
*/
class idSWFConstantPool {
public:
idSWFConstantPool();
~idSWFConstantPool() { Clear(); }
void Clear();
void Copy( const idSWFConstantPool & other );
idSWFScriptString * Get( int n ) { return pool[n]; }
void Append( idSWFScriptString * s ) { pool.Append( s ); }
private:
idList< idSWFScriptString *, TAG_SWF > pool;
};
/*
========================
The idSWFStack class is just a helper routine for treating an idList like a stack
========================
*/
class idSWFStack : public idList< idSWFScriptVar > {
public:
idSWFScriptVar & A() { return operator[]( Num() - 1 ); }
idSWFScriptVar & B() { return operator[]( Num() - 2 ); }
idSWFScriptVar & C() { return operator[]( Num() - 3 ); }
idSWFScriptVar & D() { return operator[]( Num() - 4 ); }
void Pop( int n ) { SetNum( Num() - n ); }
};
/*
========================
idSWFScriptFunction_Script is a script function that's implemented in action script
========================
*/
class idSWFScriptFunction_Script : public idSWFScriptFunction {
public:
idSWFScriptFunction_Script() : refCount( 1 ), flags( 0 ), prototype( NULL ), data( NULL ), length( 0 ), defaultSprite( NULL ) { registers.SetNum( 4 ); }
virtual ~idSWFScriptFunction_Script();
static idSWFScriptFunction_Script * Alloc() { return new (TAG_SWF) idSWFScriptFunction_Script; }
void AddRef() { refCount++; }
void Release() { if ( --refCount == 0 ) { delete this; } }
// This could all be passed to Alloc (and was at one time) but in some places it's far more convenient to specify each separately
void SetFlags( uint16 _flags ) { flags = _flags; }
void SetData( const byte * _data, uint32 _length ) { data = _data; length = _length; }
void SetScope( idList<idSWFScriptObject *> & scope );
void SetConstants( const idSWFConstantPool & _constants ) { constants.Copy( _constants ); }
void SetDefaultSprite( idSWFSpriteInstance * _sprite ) { defaultSprite = _sprite; }
void AllocRegisters( int numRegs ) { registers.SetNum( numRegs ); }
void AllocParameters( int numParms ) { parameters.SetNum( numParms ); }
void SetParameter( uint8 n, uint8 r, const char * name ) { parameters[n].reg = r; parameters[n].name = name; }
idSWFScriptObject * GetPrototype() { return prototype; }
void SetPrototype( idSWFScriptObject * _prototype ) { _prototype->AddRef(); assert( prototype == NULL ); prototype = _prototype; }
virtual idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms );
private:
idSWFScriptVar Run( idSWFScriptObject * thisObject, idSWFStack & stack, idSWFBitStream & bitstream );
private:
int refCount;
uint16 flags;
const byte * data;
uint32 length;
idSWFScriptObject * prototype;
idSWFSpriteInstance * defaultSprite; // some actions have an implicit sprite they work off of (e.g. Action_GotoFrame outside of object scope)
idList< idSWFScriptObject *, TAG_SWF > scope;
idSWFConstantPool constants;
idList< idSWFScriptVar, TAG_SWF > registers;
struct parmInfo_t {
const char * name;
uint8 reg;
};
idList< parmInfo_t, TAG_SWF > parameters;
};
#endif // !__SWF_SCRIPTFUNCTION_H__

View File

@@ -0,0 +1,580 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
idCVar swf_debugShowAddress( "swf_debugShowAddress", "0", CVAR_BOOL, "shows addresses along with object types when they are serialized" );
/*
========================
idSWFScriptObject::swfNamedVar_t::~swfNamedVar_t
========================
*/
idSWFScriptObject::swfNamedVar_t::~swfNamedVar_t() {
}
/*
========================
idSWFScriptObject::swfNamedVar_t::operator=
========================
*/
idSWFScriptObject::swfNamedVar_t & idSWFScriptObject::swfNamedVar_t::operator=( const swfNamedVar_t & other ) {
if ( &other != this ) {
index = other.index;
name = other.name;
hashNext = other.hashNext;
value = other.value;
native = other.native;
flags = other.flags;
}
return *this;
}
/*
========================
idSWFScriptObject::idSWFScriptObject
========================
*/
idSWFScriptObject::idSWFScriptObject() : prototype( NULL ), refCount( 1 ), noAutoDelete( false ), objectType( SWF_OBJECT_OBJECT ) {
data.sprite = NULL;
data.text = NULL;
Clear();
refCount = 1;
}
/*
========================
idSWFScriptObject::~idSWFScriptObject
========================
*/
idSWFScriptObject::~idSWFScriptObject() {
if ( prototype != NULL ) {
prototype->Release();
}
}
/*
========================
idSWFScriptObject::Alloc
========================
*/
idSWFScriptObject * idSWFScriptObject::Alloc() {
return new (TAG_SWF) idSWFScriptObject;
}
/*
========================
idSWFScriptObject::AddRef
========================
*/
void idSWFScriptObject::AddRef() {
refCount++;
}
/*
========================
idSWFScriptObject::Release
========================
*/
void idSWFScriptObject::Release() {
if ( --refCount == 0 && !noAutoDelete ) {
delete this;
}
}
/*
========================
idSWFScriptObject::Clear
========================
*/
void idSWFScriptObject::Clear() {
variables.Clear();
for ( int i = 0; i < VARIABLE_HASH_BUCKETS; i++ ) {
variablesHash[i] = -1;
}
}
/*
========================
idSWFScriptObject::HasProperty
========================
*/
bool idSWFScriptObject::HasProperty( const char * name ) {
return ( GetVariable( name, false ) != NULL );
}
/*
========================
idSWFScriptObject::HasValidProperty
========================
*/
bool idSWFScriptObject::HasValidProperty( const char * name ) {
idSWFScriptObject::swfNamedVar_t * const variable = GetVariable( name, false );
if ( variable == NULL ) {
return false;
}
if ( variable->native != NULL ) {
idSWFScriptVar nv = variable->native->Get( this );
if ( nv.IsNULL() || nv.IsUndefined() ) {
return false;
}
} else {
if ( variable->value.IsNULL() || variable->value.IsUndefined() ) {
return false;
}
}
return true;
}
/*
========================
idSWFScriptObject::Get
========================
*/
idSWFScriptVar idSWFScriptObject::Get( const char * name ) {
swfNamedVar_t * variable = GetVariable( name, false );
if ( variable == NULL ) {
return idSWFScriptVar();
} else {
if ( variable->native ) {
return variable->native->Get( this );
} else {
return variable->value;
}
}
}
/*
========================
idSWFScriptObject::Get
========================
*/
idSWFScriptVar idSWFScriptObject::Get( int index ) {
swfNamedVar_t * variable = GetVariable( index, false );
if ( variable == NULL ) {
return idSWFScriptVar();
} else {
if ( variable->native ) {
return variable->native->Get( this );
} else {
return variable->value;
}
}
}
/*
========================
idSWFScriptObject::GetSprite
========================
*/
idSWFSpriteInstance * idSWFScriptObject::GetSprite( int index ) {
idSWFScriptVar var = Get( index );
return var.ToSprite();
}
/*
========================
idSWFScriptObject::GetSprite
========================
*/
idSWFSpriteInstance * idSWFScriptObject::GetSprite( const char * name ) {
idSWFScriptVar var = Get( name );
return var.ToSprite();
}
/*
========================
idSWFScriptObject::GetObject
========================
*/
idSWFScriptObject * idSWFScriptObject::GetObject( int index ) {
idSWFScriptVar var = Get( index );
if ( var.IsObject() ) {
return var.GetObject();
}
return NULL;
}
/*
========================
idSWFScriptObject::GetObject
========================
*/
idSWFScriptObject * idSWFScriptObject::GetObject( const char * name ) {
idSWFScriptVar var = Get( name );
if ( var.IsObject() ) {
return var.GetObject();
}
return NULL;
}
/*
========================
idSWFScriptObject::GetText
========================
*/
idSWFTextInstance * idSWFScriptObject::GetText( int index ) {
idSWFScriptVar var = Get( index );
if ( var.IsObject() ) {
return var.GetObject()->GetText();
}
return NULL;
}
/*
========================
idSWFScriptObject::GetText
========================
*/
idSWFTextInstance * idSWFScriptObject::GetText( const char * name ) {
idSWFScriptVar var = Get( name );
if ( var.IsObject() ) {
return var.GetObject()->GetText();
}
return NULL;
}
/*
========================
idSWFScriptObject::Set
========================
*/
void idSWFScriptObject::Set( const char * name, const idSWFScriptVar & value ) {
if ( objectType == SWF_OBJECT_ARRAY ) {
if ( idStr::Cmp( name, "length" ) == 0 ) {
int newLength = value.ToInteger();
for ( int i = 0; i < variables.Num(); i++ ) {
if ( variables[i].index >= newLength ) {
variables.RemoveIndexFast( i );
i--;
}
}
// rebuild the hash table
for ( int i = 0; i < VARIABLE_HASH_BUCKETS; i++ ) {
variablesHash[i] = -1;
}
for ( int i = 0; i < variables.Num(); i++ ) {
int hash = idStr::Hash( variables[i].name.c_str() ) & ( VARIABLE_HASH_BUCKETS - 1 );
variables[i].hashNext = variablesHash[hash];
variablesHash[hash] = i;
}
} else {
int iName = atoi( name );
if ( iName > 0 || ( iName == 0 && idStr::Cmp( name, "0" ) == 0 ) ) {
swfNamedVar_t * lengthVar = GetVariable( "length", true );
if ( lengthVar->value.ToInteger() <= iName ) {
lengthVar->value = idSWFScriptVar( iName + 1 );
}
}
}
}
swfNamedVar_t * variable = GetVariable( name, true );
if ( variable->native ) {
variable->native->Set( this, value );
} else if ( ( variable->flags & SWF_VAR_FLAG_READONLY ) == 0 ) {
variable->value = value;
}
}
/*
========================
idSWFScriptObject::Set
========================
*/
void idSWFScriptObject::Set( int index, const idSWFScriptVar & value ) {
if ( index < 0 ) {
extern idCVar swf_debug;
if ( swf_debug.GetBool() ) {
idLib::Printf( "SWF: Trying to set a negative array index.\n" );
}
return;
}
if ( objectType == SWF_OBJECT_ARRAY ) {
swfNamedVar_t * lengthVar = GetVariable( "length", true );
if ( lengthVar->value.ToInteger() <= index ) {
lengthVar->value = idSWFScriptVar( index + 1 );
}
}
swfNamedVar_t * variable = GetVariable( index, true );
if ( variable->native ) {
variable->native->Set( this, value );
} else if ( ( variable->flags & SWF_VAR_FLAG_READONLY ) == 0 ) {
variable->value = value;
}
}
/*
========================
idSWFScriptObject::SetNative
========================
*/
void idSWFScriptObject::SetNative( const char * name, idSWFScriptNativeVariable * native ) {
swfNamedVar_t * variable = GetVariable( name, true );
variable->flags = SWF_VAR_FLAG_DONTENUM;
variable->native = native;
if ( native->IsReadOnly() ) {
variable->flags |= SWF_VAR_FLAG_READONLY;
}
}
/*
========================
idSWFScriptObject::DefaultValue
========================
*/
idSWFScriptVar idSWFScriptObject::DefaultValue( bool stringHint ) {
const char * methods[2] = { "toString", "valueOf" };
if ( !stringHint ) {
SwapValues( methods[0], methods[1] );
}
for ( int i = 0; i < 2; i++ ) {
idSWFScriptVar method = Get( methods[i] );
if ( method.IsFunction() ) {
idSWFScriptVar value = method.GetFunction()->Call( this, idSWFParmList() );
if ( !value.IsObject() && !value.IsFunction() ) {
return value;
}
}
}
switch ( objectType ) {
case SWF_OBJECT_OBJECT:
if ( swf_debugShowAddress.GetBool() ) {
return idSWFScriptVar( va( "[object:%p]", this ) );
} else {
return idSWFScriptVar( "[object]" );
}
case SWF_OBJECT_ARRAY:
if ( swf_debugShowAddress.GetBool() ) {
return idSWFScriptVar( va( "[array:%p]", this ) );
} else {
return idSWFScriptVar( "[array]" );
}
case SWF_OBJECT_SPRITE:
if ( data.sprite != NULL ) {
if ( data.sprite->parent == NULL ) {
return idSWFScriptVar( "[_root]" );
} else {
return idSWFScriptVar( va( "[%s]", data.sprite->GetName() ) );
}
} else {
return idSWFScriptVar( "[NULL]" );
}
case SWF_OBJECT_TEXT:
if ( swf_debugShowAddress.GetBool() ) {
return idSWFScriptVar( va( "[edittext:%p]", this ) );
} else {
return idSWFScriptVar( "[edittext]" );
}
}
return idSWFScriptVar( "[unknown]" );
}
/*
========================
idSWFScriptObject::GetVariable
========================
*/
idSWFScriptObject::swfNamedVar_t * idSWFScriptObject::GetVariable( int index, bool create ) {
for ( int i = 0; i < variables.Num(); i++ ) {
if ( variables[i].index == index ) {
return &variables[i];
}
}
if ( create ) {
swfNamedVar_t * variable = &variables.Alloc();
variable->flags = SWF_VAR_FLAG_NONE;
variable->index = index;
variable->name = va( "%d", index );
variable->native = NULL;
int hash = idStr::Hash( variable->name ) & ( VARIABLE_HASH_BUCKETS - 1 );
variable->hashNext = variablesHash[hash];
variablesHash[hash] = variables.Num() - 1;
return variable;
}
return NULL;
}
/*
========================
idSWFScriptObject::GetVariable
========================
*/
idSWFScriptObject::swfNamedVar_t * idSWFScriptObject::GetVariable( const char * name, bool create ) {
int hash = idStr::Hash( name ) & ( VARIABLE_HASH_BUCKETS - 1 );
for ( int i = variablesHash[hash]; i >= 0; i = variables[i].hashNext ) {
if ( variables[i].name == name ) {
return &variables[i];
}
}
if ( prototype != NULL ) {
swfNamedVar_t * variable = prototype->GetVariable( name, false );
if ( ( variable != NULL ) && ( variable->native || !create ) ) {
// If the variable is native, we want to pull it from the prototype even if we're going to set it
return variable;
}
}
if ( create ) {
swfNamedVar_t * variable = &variables.Alloc();
variable->flags = SWF_VAR_FLAG_NONE;
variable->index = atoi( name );
if ( variable->index == 0 && idStr::Cmp( name, "0" ) != 0 ) {
variable->index = -1;
}
variable->name = name;
variable->native = NULL;
variable->hashNext = variablesHash[hash];
variablesHash[hash] = variables.Num() - 1;
return variable;
}
return NULL;
}
/*
========================
idSWFScriptObject::MakeArray
========================
*/
void idSWFScriptObject::MakeArray() {
objectType = SWF_OBJECT_ARRAY;
swfNamedVar_t * variable = GetVariable( "length", true );
variable->value = idSWFScriptVar( 0 );
variable->flags = SWF_VAR_FLAG_DONTENUM;
}
/*
========================
idSWFScriptObject::GetNestedVar
========================
*/
idSWFScriptVar idSWFScriptObject::GetNestedVar( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
const char * const args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
const int numArgs = sizeof( args ) / sizeof( const char * );
idStaticList< const char *, numArgs > vars;
for ( int i = 0; i < numArgs && args[ i ] != NULL; ++i ) {
vars.Append( args[ i ] );
}
idSWFScriptObject * baseObject = this;
idSWFScriptVar retVal;
for ( int i = 0; i < vars.Num(); ++i ) {
idSWFScriptVar var = baseObject->Get( vars[ i ] );
// when at the end of object path just use the latest value as result
if ( i == vars.Num() - 1 ) {
retVal = var;
break;
}
// encountered variable in path that wasn't an object
if ( !var.IsObject() ) {
retVal = idSWFScriptVar();
break;
}
baseObject = var.GetObject();
}
return retVal;
}
/*
========================
idSWFScriptObject::GetNestedObj
========================
*/
idSWFScriptObject * idSWFScriptObject::GetNestedObj( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
idSWFScriptVar var = GetNestedVar( arg1, arg2, arg3, arg4, arg5, arg6 );
if ( !var.IsObject() ) {
return NULL;
}
return var.GetObject();
}
/*
========================
idSWFScriptObject::GetNestedSprite
========================
*/
idSWFSpriteInstance * idSWFScriptObject::GetNestedSprite( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
idSWFScriptVar var = GetNestedVar( arg1, arg2, arg3, arg4, arg5, arg6 );
return var.ToSprite();
}
/*
========================
idSWFScriptObject::GetNestedText
========================
*/
idSWFTextInstance * idSWFScriptObject::GetNestedText( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
idSWFScriptVar var = GetNestedVar( arg1, arg2, arg3, arg4, arg5, arg6 );
return var.ToText();
}
/*
========================
idSWFScriptObject::PrintToConsole
========================
*/
void idSWFScriptObject::PrintToConsole() const {
if ( variables.Num() > 0 ) {
idLib::Printf( "%d subelements:\n", variables.Num() );
int maxVarLength = 0;
for ( int i = 0; i < variables.Num(); ++i ) {
const idSWFScriptObject::swfNamedVar_t & nv = variables[ i ];
const int nameLength = idStr::Length( nv.name );
if ( maxVarLength < nameLength ) {
maxVarLength = nameLength;
}
}
maxVarLength += 2; // a little extra padding
const char * const fmt = va( "%%-%ds %%-10s %%-s\n", maxVarLength );
idLib::Printf( fmt, "Name", "Type", "Value" );
idLib::Printf( "------------------------------------------------------------\n" );
for ( int i = 0; i < variables.Num(); ++i ) {
const idSWFScriptObject::swfNamedVar_t & nv = variables[ i ];
idLib::Printf( fmt, nv.name.c_str(), nv.value.TypeOf(),
nv.value.ToString().c_str() );
}
} else {
idLib::Printf( "No subelements\n" );
}
}

189
neo/swf/SWF_ScriptObject.h Normal file
View File

@@ -0,0 +1,189 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SCRIPTOBJECT_H__
#define __SWF_SCRIPTOBJECT_H__
class idSWFSpriteInstance;
/*
========================
This is the base class for script variables which are implemented in code
========================
*/
class idSWFScriptNativeVariable {
public:
virtual bool IsReadOnly() { return false; }
virtual void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ) = 0;
virtual idSWFScriptVar Get( class idSWFScriptObject * object ) = 0;
};
#define SWF_NATIVE_VAR_DECLARE( x ) \
class idSWFScriptNativeVar_##x : public idSWFScriptNativeVariable { \
public: \
void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ); \
idSWFScriptVar Get( class idSWFScriptObject * object ); \
} swfScriptVar_##x;
#define SWF_NATIVE_VAR_DECLARE_READONLY( x ) \
class idSWFScriptNativeVar_##x : public idSWFScriptNativeVariable { \
public: \
bool IsReadOnly() { return true; } \
void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ) { assert( false ); } \
idSWFScriptVar Get( class idSWFScriptObject * object ); \
} swfScriptVar_##x;
/*
========================
This is a helper class for quickly setting up native variables which need access to a parent class
========================
*/
template< typename T >
class idSWFScriptNativeVariable_Nested : public idSWFScriptNativeVariable {
public:
idSWFScriptNativeVariable_Nested() : pThis( NULL ) { }
idSWFScriptNativeVariable_Nested * Bind( T * p ) { pThis = p; return this; }
virtual void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ) = 0;
virtual idSWFScriptVar Get( class idSWFScriptObject * object ) = 0;
protected:
T * pThis;
};
#define SWF_NATIVE_VAR_DECLARE_NESTED( x, y ) \
class idSWFScriptNativeVar_##x : public idSWFScriptNativeVariable_Nested<y> { \
public: \
void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ); \
idSWFScriptVar Get( class idSWFScriptObject * object ); \
} swfScriptVar_##x;
#define SWF_NATIVE_VAR_DECLARE_NESTED_READONLY( x, y, z ) \
class idSWFScriptNativeVar_##x : public idSWFScriptNativeVariable_Nested<y> { \
public: \
bool IsReadOnly() { return true; } \
void Set( class idSWFScriptObject * object, const idSWFScriptVar & value ) { assert( false ); } \
idSWFScriptVar Get( class idSWFScriptObject * object ) { return pThis->z; } \
} swfScriptVar_##x;
/*
========================
An object in an action script is a collection of variables. functions are also variables.
========================
*/
class idSWFScriptObject {
public:
idSWFScriptObject();
virtual ~idSWFScriptObject();
static idSWFScriptObject * Alloc();
void AddRef();
void Release();
void SetNoAutoDelete( bool b ) { noAutoDelete = b; }
void Clear();
void MakeArray();
void SetSprite( idSWFSpriteInstance * s ) { objectType = SWF_OBJECT_SPRITE; data.sprite = s; }
idSWFSpriteInstance * GetSprite() { return ( objectType == SWF_OBJECT_SPRITE ) ? data.sprite : NULL; }
void SetText( idSWFTextInstance * t ) { objectType = SWF_OBJECT_TEXT; data.text = t; }
idSWFTextInstance * GetText() { return ( objectType == SWF_OBJECT_TEXT ) ? data.text : NULL; }
// Also accessible via __proto__ property
idSWFScriptObject * GetPrototype() { return prototype; }
void SetPrototype( idSWFScriptObject *_prototype ) { assert( prototype == NULL ); prototype = _prototype; prototype->AddRef(); }
idSWFScriptVar Get( int index );
idSWFScriptVar Get( const char * name );
idSWFSpriteInstance * GetSprite( int index );
idSWFSpriteInstance * GetSprite( const char * name );
idSWFScriptObject * GetObject( int index );
idSWFScriptObject * GetObject( const char * name );
idSWFTextInstance * GetText( int index );
idSWFTextInstance * GetText( const char * name );
void Set( int index, const idSWFScriptVar & value );
void Set( const char * name, const idSWFScriptVar & value );
void SetNative( const char * name, idSWFScriptNativeVariable * native );
bool HasProperty( const char * name );
bool HasValidProperty( const char * name );
idSWFScriptVar DefaultValue( bool stringHint );
// This is to implement for-in (fixme: respect DONTENUM flag)
int NumVariables() { return variables.Num(); }
const char * EnumVariable( int i ) { return variables[i].name; }
idSWFScriptVar GetNestedVar( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFScriptObject * GetNestedObj( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFSpriteInstance * GetNestedSprite( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFTextInstance * GetNestedText( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
void PrintToConsole() const;
private:
int refCount;
bool noAutoDelete;
enum swfNamedVarFlags_t {
SWF_VAR_FLAG_NONE = 0,
SWF_VAR_FLAG_READONLY = BIT(1),
SWF_VAR_FLAG_DONTENUM = BIT(2)
};
struct swfNamedVar_t {
swfNamedVar_t() : native( NULL ) { }
~swfNamedVar_t();
swfNamedVar_t & operator=( const swfNamedVar_t & other );
int index;
int hashNext;
idStr name;
idSWFScriptVar value;
idSWFScriptNativeVariable * native;
int flags;
};
idList< swfNamedVar_t, TAG_SWF > variables;
static const int VARIABLE_HASH_BUCKETS = 16;
int variablesHash[VARIABLE_HASH_BUCKETS];
idSWFScriptObject * prototype;
enum swfObjectType_t {
SWF_OBJECT_OBJECT,
SWF_OBJECT_ARRAY,
SWF_OBJECT_SPRITE,
SWF_OBJECT_TEXT
} objectType;
union swfObjectData_t {
idSWFSpriteInstance * sprite; // only valid if objectType == SWF_OBJECT_SPRITE
idSWFTextInstance * text; // only valid if objectType == SWF_OBJECT_TEXT
} data;
swfNamedVar_t * GetVariable( int index, bool create );
swfNamedVar_t * GetVariable( const char * name, bool create );
};
#endif // !__SWF_SCRIPTOBJECT_H__

422
neo/swf/SWF_ScriptVar.cpp Normal file
View File

@@ -0,0 +1,422 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
extern idCVar swf_debugShowAddress;
/*
========================
idSWFScriptVar::idSWFScriptVar
========================
*/
idSWFScriptVar::idSWFScriptVar( const idSWFScriptVar & other ) {
type = other.type;
value = other.value;
if ( other.type == SWF_VAR_STRING ) {
other.value.string->AddRef();
} else if ( other.type == SWF_VAR_OBJECT ) {
other.value.object->AddRef();
} else if ( other.type == SWF_VAR_FUNCTION ) {
other.value.function->AddRef();
}
}
/*
========================
idSWFScriptVar::operator=
========================
*/
idSWFScriptVar & idSWFScriptVar::operator=( const idSWFScriptVar & other ) {
if ( this != &other ) {
Free();
type = other.type;
value = other.value;
if ( other.type == SWF_VAR_STRING ) {
other.value.string->AddRef();
} else if ( other.type == SWF_VAR_OBJECT ) {
other.value.object->AddRef();
} else if ( other.type == SWF_VAR_FUNCTION ) {
other.value.function->AddRef();
}
}
return *this;
}
/*
========================
idSWFScriptVar::~idSWFScriptVar
========================
*/
idSWFScriptVar::~idSWFScriptVar() {
Free();
}
/*
========================
idSWFScriptVar::Free
========================
*/
void idSWFScriptVar::Free() {
if ( type == SWF_VAR_STRING ) {
value.string->Release();
} else if ( type == SWF_VAR_OBJECT ) {
value.object->Release();
} else if ( type == SWF_VAR_FUNCTION ) {
value.function->Release();
}
value.string = NULL;
value.function = NULL;
value.object = NULL;
type = SWF_VAR_UNDEF;
}
/*
========================
idSWFScriptVar::SetObject
========================
*/
void idSWFScriptVar::SetObject( idSWFScriptObject * o ) {
Free();
if ( o == NULL ) {
type = SWF_VAR_NULL;
} else {
type = SWF_VAR_OBJECT;
value.object = o;
o->AddRef();
}
}
/*
========================
idSWFScriptVar::SetFunction
========================
*/
void idSWFScriptVar::SetFunction( idSWFScriptFunction * f ) {
Free();
if ( f == NULL ) {
type = SWF_VAR_NULL;
} else {
type = SWF_VAR_FUNCTION;
value.function = f;
f->AddRef();
}
}
/*
========================
idSWFScriptVar::StrictEquals
========================
*/
bool idSWFScriptVar::StrictEquals( const idSWFScriptVar & other ) {
if ( type != other.type ) {
return false;
}
switch ( type ) {
case SWF_VAR_STRINGID: return ( value.i == other.value.i );
case SWF_VAR_STRING: return ( *value.string == *other.value.string );
case SWF_VAR_FLOAT: return ( value.f == other.value.f );
case SWF_VAR_BOOL: return ( value.b == other.value.b );
case SWF_VAR_INTEGER: return ( value.i == other.value.i );
case SWF_VAR_NULL: return true;
case SWF_VAR_UNDEF: return true;
case SWF_VAR_OBJECT: return ( value.object == other.value.object );
case SWF_VAR_FUNCTION: return ( value.function == other.value.function );
default: assert( false ); return false;
}
}
/*
========================
idSWFScriptVar::AbstractEquals
========================
*/
bool idSWFScriptVar::AbstractEquals( const idSWFScriptVar & other ) {
if ( type == other.type ) {
switch ( type ) {
case SWF_VAR_STRINGID: return ( value.i == other.value.i );
case SWF_VAR_STRING: return ( *value.string == *other.value.string );
case SWF_VAR_FLOAT: return ( value.f == other.value.f );
case SWF_VAR_BOOL: return ( value.b == other.value.b );
case SWF_VAR_INTEGER: return ( value.i == other.value.i );
case SWF_VAR_NULL: return true;
case SWF_VAR_UNDEF: return true;
case SWF_VAR_OBJECT: return ( value.object == other.value.object );
case SWF_VAR_FUNCTION: return ( value.function == other.value.function );
default: assert( false ); return false;
}
}
switch ( type ) {
case SWF_VAR_STRINGID: return ToString() == other.ToString();
case SWF_VAR_STRING:
switch ( other.type ) {
case SWF_VAR_STRINGID: return *value.string == other.ToString();
case SWF_VAR_FLOAT: return ToFloat() == other.value.f;
case SWF_VAR_BOOL: return ToBool() == other.value.b;
case SWF_VAR_INTEGER: return ToInteger() == other.value.i;
case SWF_VAR_OBJECT: return *value.string == other.ToString();
default: return false;
}
case SWF_VAR_FLOAT: return ( other.ToFloat() == value.f );
case SWF_VAR_BOOL: return ( other.ToBool() == value.b );
case SWF_VAR_INTEGER: return ( other.ToInteger() == value.i );
case SWF_VAR_NULL: return ( other.type == SWF_VAR_UNDEF );
case SWF_VAR_UNDEF: return ( other.type == SWF_VAR_NULL );
case SWF_VAR_OBJECT:
switch ( other.type ) {
case SWF_VAR_STRING: return ToString() == *other.value.string;
case SWF_VAR_FLOAT: return ToFloat() == other.value.f;
case SWF_VAR_BOOL: return ToBool() == other.value.b;
case SWF_VAR_INTEGER: return ToInteger() == other.value.i;
default: return false;
}
case SWF_VAR_FUNCTION: return false;
default: assert( false ); return false;
}
}
/*
========================
idSWFScriptVar::ToString
========================
*/
idStr idSWFScriptVar::ToString() const {
switch ( type ) {
case SWF_VAR_STRINGID: return idStrId( value.i ).GetLocalizedString();
case SWF_VAR_STRING: return *value.string;
case SWF_VAR_FLOAT: return va( "%g", value.f );
case SWF_VAR_BOOL: return value.b ? "true" : "false";
case SWF_VAR_INTEGER: return va( "%i", value.i );
case SWF_VAR_NULL: return "[null]";
case SWF_VAR_UNDEF: return "[undefined]";
case SWF_VAR_OBJECT: return value.object->DefaultValue( true ).ToString();
case SWF_VAR_FUNCTION:
if ( swf_debugShowAddress.GetBool() ) {
return va( "[function:%p]", value.function );
} else {
return "[function]";
}
default: assert( false ); return "";
}
}
/*
========================
idSWFScriptVar::ToFloat
========================
*/
float idSWFScriptVar::ToFloat() const {
switch ( type ) {
case SWF_VAR_STRING: return atof( *value.string );
case SWF_VAR_FLOAT: return value.f;
case SWF_VAR_BOOL: return (float)value.b;
case SWF_VAR_INTEGER: return (float)value.i;
case SWF_VAR_OBJECT: return value.object->DefaultValue( false ).ToFloat();
case SWF_VAR_FUNCTION:
case SWF_VAR_NULL:
case SWF_VAR_UNDEF: return 0.0f;
default: assert( false ); return 0.0f;
}
}
/*
========================
idSWFScriptVar::ToBool
========================
*/
bool idSWFScriptVar::ToBool() const {
switch ( type ) {
case SWF_VAR_STRING: return ( value.string->Icmp( "true" ) == 0 || value.string->Icmp( "1" ) == 0 );
case SWF_VAR_FLOAT: return ( value.f != 0.0f );
case SWF_VAR_BOOL: return value.b;
case SWF_VAR_INTEGER: return value.i != 0;
case SWF_VAR_OBJECT: return value.object->DefaultValue( false ).ToBool();
case SWF_VAR_FUNCTION:
case SWF_VAR_NULL:
case SWF_VAR_UNDEF: return false;
default: assert( false ); return false;
}
}
/*
========================
idSWFScriptVar::ToInteger
========================
*/
int32 idSWFScriptVar::ToInteger() const {
switch ( type ) {
case SWF_VAR_STRING: return atoi( *value.string );
case SWF_VAR_FLOAT: return idMath::Ftoi( value.f );
case SWF_VAR_BOOL: return value.b ? 1 : 0;
case SWF_VAR_INTEGER: return value.i;
case SWF_VAR_OBJECT: return value.object->DefaultValue( false ).ToInteger();
case SWF_VAR_FUNCTION:
case SWF_VAR_NULL:
case SWF_VAR_UNDEF: return 0;
default: assert( false ); return 0;
}
}
/*
========================
idSWFScriptVar::ToSprite
========================
*/
idSWFSpriteInstance * idSWFScriptVar::ToSprite() {
if ( IsObject() && value.object != NULL ) {
return value.object->GetSprite();
}
return NULL;
}
/*
========================
idSWFScriptVar::ToText
========================
*/
idSWFTextInstance * idSWFScriptVar::ToText() {
if ( IsObject() && value.object != NULL ) {
return value.object->GetText();
}
return NULL;
}
/*
========================
idSWFScriptVar::GetNestedVar
========================
*/
idSWFScriptVar idSWFScriptVar::GetNestedVar( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
if ( !IsObject() ) {
return idSWFScriptVar();
}
return GetObject()->GetNestedVar( arg1, arg2, arg3, arg4, arg5, arg6 );
}
/*
========================
idSWFScriptVar::GetNestedObj
========================
*/
idSWFScriptObject * idSWFScriptVar::GetNestedObj( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
if ( !IsObject() ) {
return NULL;
}
return GetObject()->GetNestedObj( arg1, arg2, arg3, arg4, arg5, arg6 );
}
/*
========================
idSWFScriptVar::GetNestedSprite
========================
*/
idSWFSpriteInstance * idSWFScriptVar::GetNestedSprite( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
if ( !IsObject() ) {
return NULL;
}
return GetObject()->GetNestedSprite( arg1, arg2, arg3, arg4, arg5, arg6 );
}
/*
========================
idSWFScriptVar::GetNestedSprite
========================
*/
idSWFTextInstance * idSWFScriptVar::GetNestedText( const char * arg1, const char * arg2, const char * arg3, const char * arg4, const char * arg5, const char * arg6 ) {
if ( !IsObject() ) {
return NULL;
}
return GetObject()->GetNestedText( arg1, arg2, arg3, arg4, arg5, arg6 );
}
/*
========================
idSWFScriptVar::TypeOf
========================
*/
const char * idSWFScriptVar::TypeOf() const {
switch ( type ) {
case SWF_VAR_STRINGID: return "stringid";
case SWF_VAR_STRING: return "string";
case SWF_VAR_FLOAT: return "number";
case SWF_VAR_BOOL: return "boolean";
case SWF_VAR_INTEGER: return "number";
case SWF_VAR_OBJECT:
if ( value.object->GetSprite() != NULL ) {
return "movieclip";
} else if ( value.object->GetText() != NULL ) {
return "text";
} else {
return "object";
}
case SWF_VAR_FUNCTION: return "function";
case SWF_VAR_NULL: return "null";
case SWF_VAR_UNDEF: return "undefined";
default: assert( false ); return "";
}
}
/*
========================
idSWFScriptVar::PrintToConsole
========================
*/
void idSWFScriptVar::PrintToConsole() const {
idLib::Printf( "Object type: %s\n", TypeOf() );
if ( IsObject() ) {
GetObject()->PrintToConsole();
} else if ( IsNumeric() ) {
idLib::Printf( "%d\n", ToInteger() );
} else if ( IsString() ) {
idLib::Printf( "%s\n", ToString().c_str() );
} else {
idLib::Printf( "unknown\n" );
}
}

148
neo/swf/SWF_ScriptVar.h Normal file
View File

@@ -0,0 +1,148 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SCRIPTVAR_H__
#define __SWF_SCRIPTVAR_H__
class idSWFScriptObject;
class idSWFScriptFunction;
/*
========================
A reference counted string
========================
*/
class idSWFScriptString : public idStr {
public:
idSWFScriptString( const idStr & s ) : idStr( s ), refCount( 1 ) { }
static idSWFScriptString * Alloc( const idStr & s ) { return new (TAG_SWF) idSWFScriptString( s ); }
ID_INLINE void AddRef() { refCount++; }
ID_INLINE void Release() { if ( --refCount == 0 ) { delete this; } }
private:
int refCount;
};
/*
========================
A variable in an action script
these can be on the stack, in a script object, passed around as parameters, etc
they can contain raw data (int, float), strings, functions, or objects
========================
*/
class idSWFScriptVar {
public:
idSWFScriptVar() : type( SWF_VAR_UNDEF ) { }
idSWFScriptVar( const idSWFScriptVar & other );
idSWFScriptVar( idSWFScriptObject * o ) : type( SWF_VAR_UNDEF ) { SetObject( o ); }
idSWFScriptVar( idStrId s ) : type( SWF_VAR_UNDEF ) { SetString( s ); }
idSWFScriptVar( const idStr & s ) : type( SWF_VAR_UNDEF ) { SetString( s ); }
idSWFScriptVar( const char * s ) : type( SWF_VAR_UNDEF ) { SetString( idStr( s ) ); }
idSWFScriptVar( float f ) : type( SWF_VAR_UNDEF ) { SetFloat( f ); }
idSWFScriptVar( bool b ) : type( SWF_VAR_UNDEF ) { SetBool( b ); }
idSWFScriptVar( int32 i ) : type( SWF_VAR_UNDEF ) { SetInteger( i ); }
idSWFScriptVar( idSWFScriptFunction * nf ) : type( SWF_VAR_UNDEF ) { SetFunction( nf ); }
~idSWFScriptVar();
idSWFScriptVar & operator=( const idSWFScriptVar & other );
// implements ECMA 262 11.9.3
bool AbstractEquals( const idSWFScriptVar & other );
bool StrictEquals( const idSWFScriptVar & other );
void SetString( idStrId s ) { Free(); type = SWF_VAR_STRINGID; value.i = s.GetIndex(); }
void SetString( const idStr & s ) { Free(); type = SWF_VAR_STRING; value.string = idSWFScriptString::Alloc( s ); }
void SetString( const char * s ) { Free(); type = SWF_VAR_STRING; value.string = idSWFScriptString::Alloc( s ); }
void SetString( idSWFScriptString * s ) { Free(); type = SWF_VAR_STRING; value.string = s; s->AddRef(); }
void SetFloat( float f ) { Free(); type = SWF_VAR_FLOAT; value.f = f; }
void SetNULL() { Free(); type = SWF_VAR_NULL; }
void SetUndefined() { Free(); type = SWF_VAR_UNDEF; }
void SetBool( bool b ) { Free(); type = SWF_VAR_BOOL; value.b = b; }
void SetInteger( int32 i ) { Free(); type = SWF_VAR_INTEGER; value.i = i; }
void SetObject( idSWFScriptObject * o );
void SetFunction( idSWFScriptFunction * f );
idStr ToString() const;
float ToFloat() const;
bool ToBool() const;
int32 ToInteger() const;
idSWFScriptObject * GetObject() { assert( type == SWF_VAR_OBJECT ); return value.object; }
idSWFScriptObject * GetObject() const { assert( type == SWF_VAR_OBJECT ); return value.object; }
idSWFScriptFunction * GetFunction() { assert( type == SWF_VAR_FUNCTION ); return value.function; }
idSWFSpriteInstance * ToSprite();
idSWFTextInstance * ToText();
idSWFScriptVar GetNestedVar( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFScriptObject * GetNestedObj( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFSpriteInstance * GetNestedSprite( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
idSWFTextInstance * GetNestedText( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL, const char * arg6 = NULL );
const char * TypeOf() const;
// debug print of this variable to the console
void PrintToConsole() const;
bool IsString() const { return ( type == SWF_VAR_STRING ) || ( type == SWF_VAR_STRINGID ); }
bool IsNULL() const { return ( type == SWF_VAR_NULL ); }
bool IsUndefined() const { return ( type == SWF_VAR_UNDEF ); }
bool IsValid() const { return ( type != SWF_VAR_UNDEF ) && ( type != SWF_VAR_NULL ); }
bool IsFunction() const { return ( type == SWF_VAR_FUNCTION ); }
bool IsObject() const { return ( type == SWF_VAR_OBJECT ); }
bool IsNumeric() const { return ( type == SWF_VAR_FLOAT ) || ( type == SWF_VAR_INTEGER ) || ( type == SWF_VAR_BOOL ); }
enum swfScriptVarType {
SWF_VAR_STRINGID,
SWF_VAR_STRING,
SWF_VAR_FLOAT,
SWF_VAR_NULL,
SWF_VAR_UNDEF,
SWF_VAR_BOOL,
SWF_VAR_INTEGER,
SWF_VAR_FUNCTION,
SWF_VAR_OBJECT
};
swfScriptVarType GetType() const { return type; }
private:
void Free();
swfScriptVarType type;
union swfScriptVarValue_t {
float f;
int32 i;
bool b;
idSWFScriptObject * object;
idSWFScriptString * string;
idSWFScriptFunction * function;
} value;
};
#endif // !__SWF_SCRIPTVAR_H__

903
neo/swf/SWF_ShapeParser.cpp Normal file
View File

@@ -0,0 +1,903 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "float.h"
#pragma warning( disable: 4189 ) // local variable is initialized but not referenced
/*
========================
idSWFShapeParser::ParseShape
========================
*/
void idSWFShapeParser::Parse( idSWFBitStream & bitstream, idSWFShape & shape, int recordType ) {
extendedCount = ( recordType > 1 );
lineStyle2 = ( recordType == 4 );
rgba = ( recordType >= 3 );
morph = false;
bitstream.ReadRect( shape.startBounds );
shape.endBounds = shape.startBounds;
if ( recordType == 4 ) {
swfRect_t edgeBounds;
bitstream.ReadRect( edgeBounds );
bitstream.ReadU8(); // flags (that we ignore)
}
ReadFillStyle( bitstream );
ParseShapes( bitstream, NULL, false );
TriangulateSoup( shape );
shape.lineDraws.SetNum( lineDraws.Num() );
for ( int i = 0; i < lineDraws.Num(); i++ ) {
idSWFShapeDrawLine & ld = shape.lineDraws[i];
swfSPDrawLine_t & spld = lineDraws[i];
ld.style = spld.style;
ld.indices.SetNum( spld.edges.Num() * 3 );
ld.indices.SetNum( 0 );
for ( int e = 0; e < spld.edges.Num(); e++ ) {
int v0 = ld.startVerts.AddUnique( verts[ spld.edges[e].start.v0 ] );
ld.indices.Append( v0 );
ld.indices.Append( v0 );
// Rather then tesselating curves at run time, we do them once here by inserting a vert every 10 units
// It may not wind up being 10 actual pixels when rendered because the shape may have scaling applied to it
if ( spld.edges[e].start.cp != 0xFFFF ) {
assert( spld.edges[e].end.cp != 0xFFFF );
float length1 = ( verts[ spld.edges[e].start.v0 ] - verts[ spld.edges[e].start.v1 ] ).Length();
float length2 = ( verts[ spld.edges[e].end.v0 ] - verts[ spld.edges[e].end.v1 ] ).Length();
int numPoints = 1 + idMath::Ftoi( Max( length1, length2 ) / 10.0f );
for ( int ti = 0; ti < numPoints; ti++ ) {
float t0 = ( ti + 1 ) / ( (float) numPoints + 1.0f );
float t1 = ( 1.0f - t0 );
float c1 = t1 * t1;
float c2 = t0 * t1 * 2.0f;
float c3 = t0 * t0;
idVec2 p1 = c1 * verts[ spld.edges[e].start.v0 ];
p1 += c2 * verts[ spld.edges[e].start.cp ];
p1 += c3 * verts[ spld.edges[e].start.v1 ];
int v1 = ld.startVerts.AddUnique( p1 );
ld.indices.Append( v1 );
ld.indices.Append( v1 );
ld.indices.Append( v1 );
}
}
ld.indices.Append( ld.startVerts.AddUnique( verts[ spld.edges[e].start.v1 ] ) );
}
}
}
/*
========================
idSWFShapeParser::ParseMorph
========================
*/
void idSWFShapeParser::ParseMorph( idSWFBitStream & bitstream, idSWFShape & shape ) {
extendedCount = true;
lineStyle2 = false;
rgba = true;
morph = true;
bitstream.ReadRect( shape.startBounds );
bitstream.ReadRect( shape.endBounds );
uint32 offset = bitstream.ReadU32();
// offset is the byte offset from the current read position to the 'endShape' record
// we read the entire block into 'bitstream1' which moves the read pointer of 'bitstream'
// to the start of the 'endShape' record
idSWFBitStream bitstream1;
bitstream1.Load( (byte *)bitstream.ReadData( offset ), offset, false );
ReadFillStyle( bitstream1 );
ParseShapes( bitstream1, &bitstream, true );
TriangulateSoup( shape );
}
/*
========================
idSWFShapeParser::ParseFont
========================
*/
void idSWFShapeParser::ParseFont( idSWFBitStream & bitstream, idSWFFontGlyph & shape ) {
extendedCount = false;
lineStyle2 = false;
rgba = false;
morph = false;
fillDraws.SetNum( 1 );
ParseShapes( bitstream, NULL, true );
TriangulateSoup( shape );
}
/*
========================
idSWFShapeParser::ParseShapes
========================
*/
void idSWFShapeParser::ParseShapes( idSWFBitStream & bitstream1, idSWFBitStream * bitstream2, bool swap ) {
int32 pen1X = 0;
int32 pen1Y = 0;
int32 pen2X = 0;
int32 pen2Y = 0;
uint8 fillStyle0 = 0;
uint8 fillStyle1 = 0;
uint8 lineStyle = 0;
uint16 baseFillStyle = 0;
uint16 baseLineStyle = 0;
uint8 numBits = bitstream1.ReadU8();
uint8 numFillBits1 = numBits >> 4;
uint8 numLineBits1 = numBits & 0xF;
uint8 numFillBits2 = 0;
uint8 numLineBits2 = 0;
if ( bitstream2 ) {
numBits = bitstream2->ReadU8();
numFillBits2 = numBits >> 4;
numLineBits2 = numBits & 0xF;
}
while ( true ) {
if ( !bitstream1.ReadBool() ) {
bool stateNewStyles = bitstream1.ReadBool();
bool stateLineStyle = bitstream1.ReadBool();
bool stateFillStyle1 = bitstream1.ReadBool();
bool stateFillStyle0 = bitstream1.ReadBool();
bool stateMoveTo = bitstream1.ReadBool();
if ( ( stateNewStyles || stateLineStyle || stateFillStyle1 || stateFillStyle0 || stateMoveTo ) == false ) {
// end record
if ( bitstream2 ) {
uint8 flags = bitstream2->ReadU( 6 );
if ( flags != 0 ) {
idLib::Warning( "idSWFShapeParser: morph stream 1 ends before 2" );
break;
}
}
break;
}
if ( stateMoveTo ) {
uint8 moveBits = bitstream1.ReadU( 5 );
pen1X = bitstream1.ReadS( moveBits );
pen1Y = bitstream1.ReadS( moveBits );
}
if ( stateFillStyle0 ) {
fillStyle0 = bitstream1.ReadU( numFillBits1 );
}
if ( stateFillStyle1 ) {
fillStyle1 = bitstream1.ReadU( numFillBits1 );
}
if ( stateLineStyle ) {
lineStyle = bitstream1.ReadU( numLineBits1 );
}
if ( stateNewStyles ) {
baseFillStyle = fillDraws.Num();
baseLineStyle = lineDraws.Num();
ReadFillStyle( bitstream1 );
numBits = bitstream1.ReadU8();
numFillBits1 = numBits >> 4;
numLineBits1 = numBits & 0xF;
}
if ( bitstream2 ) {
bool isEdge = bitstream2->ReadBool();
if ( isEdge ) {
idLib::Warning( "idSWFShapeParser: morph stream 1 defines style change, but stream 2 does not" );
break;
}
bool stateNewStyles = bitstream2->ReadBool();
bool stateLineStyle = bitstream2->ReadBool();
bool stateFillStyle1 = bitstream2->ReadBool();
bool stateFillStyle0 = bitstream2->ReadBool();
bool stateMoveTo = bitstream2->ReadBool();
if ( stateMoveTo ) {
uint8 moveBits = bitstream2->ReadU( 5 );
pen2X = bitstream2->ReadS( moveBits );
pen2Y = bitstream2->ReadS( moveBits );
}
if ( stateFillStyle0 ) {
if ( bitstream2->ReadU( numFillBits2 ) != fillStyle0 ) {
idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different fillStyle0 from stream 1" );
break;
}
}
if ( stateFillStyle1 ) {
if ( bitstream2->ReadU( numFillBits2 ) != fillStyle1 ) {
idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different fillStyle1 from stream 1" );
break;
}
}
if ( stateLineStyle ) {
if ( bitstream2->ReadU( numLineBits2 ) != lineStyle ) {
idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different lineStyle from stream 1" );
break;
}
}
if ( stateNewStyles ) {
idLib::Warning( "idSWFShapeParser: morph stream 2 defines new styles" );
break;
}
}
} else {
swfSPMorphEdge_t morphEdge;
ParseEdge( bitstream1, pen1X, pen1Y, morphEdge.start );
if ( bitstream2 ) {
bool isEdge = bitstream2->ReadBool();
if ( !isEdge ) {
idLib::Warning( "idSWFShapeParser: morph stream 1 defines an edge, but stream 2 does not" );
break;
}
ParseEdge( *bitstream2, pen2X, pen2Y, morphEdge.end );
} else {
morphEdge.end = morphEdge.start;
}
// one edge may be a straight edge, and the other may be a curve
// in this case, we turn the straight edge into a curve by adding
// a control point in the middle of the line
if ( morphEdge.start.cp != 0xFFFF ) {
if ( morphEdge.end.cp == 0xFFFF ) {
const idVec2 & v0 = verts[ morphEdge.end.v0 ];
const idVec2 & v1 = verts[ morphEdge.end.v1 ];
morphEdge.end.cp = verts.AddUnique( ( v0 + v1 ) * 0.5f );
}
} else {
if ( morphEdge.end.cp != 0xFFFF ) {
const idVec2 & v0 = verts[ morphEdge.start.v0 ];
const idVec2 & v1 = verts[ morphEdge.start.v1 ];
morphEdge.start.cp = verts.AddUnique( ( v0 + v1 ) * 0.5f );
}
}
if ( lineStyle != 0 ) {
lineDraws[ baseLineStyle + lineStyle - 1 ].edges.Append( morphEdge );
}
if ( swap ) {
SwapValues( morphEdge.start.v0, morphEdge.start.v1 );
SwapValues( morphEdge.end.v0, morphEdge.end.v1 );
}
if ( fillStyle1 != 0 ) {
fillDraws[ baseFillStyle + fillStyle1 - 1 ].edges.Append( morphEdge );
}
if ( fillStyle0 != 0 ) {
// for fill style 0, we need to reverse the winding
swfSPMorphEdge_t swapped = morphEdge;
SwapValues( swapped.start.v0, swapped.start.v1 );
SwapValues( swapped.end.v0, swapped.end.v1 );
fillDraws[ baseFillStyle + fillStyle0 - 1 ].edges.Append( swapped );
}
}
}
}
/*
========================
idSWFShapeParser::ParseEdge
========================
*/
void idSWFShapeParser::ParseEdge( idSWFBitStream & bitstream, int32 & penX, int32 & penY, swfSPEdge_t & edge ) {
bool straight = bitstream.ReadBool();
uint8 numBits = bitstream.ReadU( 4 ) + 2;
edge.v0 = verts.AddUnique( idVec2( SWFTWIP( penX ), SWFTWIP( penY ) ) );
if ( straight ) {
edge.cp = 0xFFFF;
if ( bitstream.ReadBool() ) {
penX += bitstream.ReadS( numBits );
penY += bitstream.ReadS( numBits );
} else {
if ( bitstream.ReadBool() ) {
penY += bitstream.ReadS( numBits );
} else {
penX += bitstream.ReadS( numBits );
}
}
} else {
penX += bitstream.ReadS( numBits );
penY += bitstream.ReadS( numBits );
edge.cp = verts.AddUnique( idVec2( SWFTWIP( penX ), SWFTWIP( penY ) ) );
penX += bitstream.ReadS( numBits );
penY += bitstream.ReadS( numBits );
}
edge.v1 = verts.AddUnique( idVec2( SWFTWIP( penX ), SWFTWIP( penY ) ) );
}
/*
========================
idSWFShapeParser::MakeLoops
========================
*/
void idSWFShapeParser::MakeLoops() {
// At this point, each fill style has an edge soup associated with it
// We want to turn this soup into loops of connected verts
for ( int i = 0; i < fillDraws.Num(); i++ ) {
swfSPDrawFill_t & fill = fillDraws[i];
// first remove degenerate edges
for ( int e = 0; e < fill.edges.Num(); e++ ) {
if ( ( fill.edges[e].start.v0 == fill.edges[e].start.v1 ) || ( fill.edges[e].end.v0 == fill.edges[e].end.v1 ) ) {
fill.edges.RemoveIndexFast( e );
e--;
}
}
idList< int > unusedEdges;
unusedEdges.SetNum( fill.edges.Num() );
for ( int e = 0; e < fill.edges.Num(); e++ ) {
unusedEdges[e] = e;
}
while ( unusedEdges.Num() > 0 ) {
swfSPLineLoop_t & loop = fill.loops.Alloc();
loop.hole = false;
int e1 = unusedEdges[ unusedEdges.Num() - 1 ];
unusedEdges.SetNum( unusedEdges.Num() - 1 );
while ( true ) {
loop.vindex1.Append( fill.edges[e1].start.v0 );
loop.vindex2.Append( fill.edges[e1].end.v0 );
// Rather then tesselating curves at run time, we do them once here by inserting a vert every 10 units
// It may not wind up being 10 actual pixels when rendered because the shape may have scaling applied to it
if ( fill.edges[e1].start.cp != 0xFFFF ) {
assert( fill.edges[e1].end.cp != 0xFFFF );
float length1 = ( verts[ fill.edges[e1].start.v0 ] - verts[ fill.edges[e1].start.v1 ] ).Length();
float length2 = ( verts[ fill.edges[e1].end.v0 ] - verts[ fill.edges[e1].end.v1 ] ).Length();
int numPoints = 1 + idMath::Ftoi( Max( length1, length2 ) / 10.0f );
for ( int ti = 0; ti < numPoints; ti++ ) {
float t0 = ( ti + 1 ) / ( (float) numPoints + 1.0f );
float t1 = ( 1.0f - t0 );
float c1 = t1 * t1;
float c2 = t0 * t1 * 2.0f;
float c3 = t0 * t0;
idVec2 p1 = c1 * verts[ fill.edges[e1].start.v0 ];
p1 += c2 * verts[ fill.edges[e1].start.cp ];
p1 += c3 * verts[ fill.edges[e1].start.v1 ];
idVec2 p2 = c1 * verts[ fill.edges[e1].end.v0 ];
p2 += c2 * verts[ fill.edges[e1].end.cp ];
p2 += c3 * verts[ fill.edges[e1].end.v1 ];
loop.vindex1.Append( verts.AddUnique( p1 ) );
loop.vindex2.Append( verts.AddUnique( p2 ) );
}
}
const swfSPEdge_t & edge1 = fill.edges[e1].start;
float bestNormal = FLT_MAX;
int beste = -1;
for ( int e = 0; e < unusedEdges.Num(); e++ ) {
int e2 = unusedEdges[e];
const swfSPEdge_t & edge2 = fill.edges[e2].start;
if ( edge1.v1 != edge2.v0 ) {
continue;
}
assert( edge1.v0 != edge2.v0 );
assert( edge1.v1 != edge2.v1 );
const idVec2 & v1 = verts[ edge1.v0 ];
const idVec2 & v2 = verts[ edge1.v1 ]; // == edge2.v0
const idVec2 & v3 = verts[ edge2.v1 ];
idVec2 a = v1 - v2;
idVec2 b = v3 - v2;
float normal = ( a.x * b.y - a.y * b.x );
if ( normal < bestNormal ) {
bestNormal = normal;
beste = e;
} else {
assert( beste != -1 );
}
}
if ( beste < 0 ) {
// no more edges connect to this one
break;
}
e1 = unusedEdges[beste];
unusedEdges.RemoveIndexFast( beste );
}
if ( loop.vindex1.Num() < 3 ) {
idLib::Warning( "idSWFShapeParser: loop with < 3 verts" );
fill.loops.SetNum( fill.loops.Num() - 1 );
continue;
}
// Use the left most vert to determine if it's a hole or not
float leftMostX = FLT_MAX;
int leftMostIndex = 0;
for ( int j = 0; j < loop.vindex1.Num(); j++ ) {
idVec2 & v = verts[ loop.vindex1[j] ];
if ( v.x < leftMostX ) {
leftMostIndex = j;
leftMostX = v.x;
}
}
const idVec2 & v1 = verts[ loop.vindex1[(loop.vindex1.Num() + leftMostIndex - 1) % loop.vindex1.Num()] ];
const idVec2 & v2 = verts[ loop.vindex1[leftMostIndex] ];
const idVec2 & v3 = verts[ loop.vindex1[(leftMostIndex+1) % loop.vindex1.Num()] ];
idVec2 a = v1 - v2;
idVec2 b = v3 - v2;
float normal = ( a.x * b.y - a.y * b.x );
loop.hole = ( normal > 0.0f );
}
// now we have a series of loops, which define either shapes or holes
// we want to merge the holes into the shapes by inserting edges
// this assumes shapes are either completely contained or not
// we start merging holes starting on the right so nested holes work
while ( true ) {
int hole = -1;
int holeVert = -1;
float rightMostX = -1e10f;
for ( int j = 0; j < fill.loops.Num(); j++ ) {
swfSPLineLoop_t & loop = fill.loops[j];
if ( !loop.hole ) {
continue;
}
for ( int v = 0; v < loop.vindex1.Num(); v++ ) {
if ( verts[ loop.vindex1[v] ].x > rightMostX ) {
hole = j;
holeVert = v;
rightMostX = verts[ loop.vindex1[v] ].x;
}
}
}
if ( hole == -1 ) {
break;
}
swfSPLineLoop_t & loopHole = fill.loops[ hole ];
const idVec2 & holePoint = verts[ loopHole.vindex1[ holeVert ] ];
int shape = -1;
for ( int j = 0; j < fill.loops.Num(); j++ ) {
swfSPLineLoop_t & loop = fill.loops[j];
if ( loop.hole ) {
continue;
}
bool inside = false;
for ( int k = 0; k < loop.vindex1.Num(); k++ ) {
const idVec2 & v1 = verts[ loop.vindex1[k] ];
const idVec2 & v2 = verts[ loop.vindex1[(k + 1) % loop.vindex1.Num()] ];
if ( v1.x < holePoint.x && v2.x < holePoint.x ) {
continue; // both on the left of the holePoint
}
if ( ( v1.y < holePoint.y ) == ( v2.y < holePoint.y ) ) {
continue; // both on the same side of the horizon
}
assert( v1 != holePoint );
assert( v2 != holePoint );
inside = !inside;
}
if ( inside ) {
shape = j;
break;
}
}
if ( shape == -1 ) {
idLib::Warning( "idSWFShapeParser: Hole not in a shape" );
fill.loops.RemoveIndexFast( hole );
continue;
}
swfSPLineLoop_t & loopShape = fill.loops[ shape ];
// now that we have a hole and the shape it's inside, merge the two together
// find the nearest vert that's on the right side of holePoint
float bestDist = 1e10f;
int shapeVert = -1;
for ( int j = 0; j < loopShape.vindex1.Num(); j++ ) {
const idVec2 & v1 = verts[ loopShape.vindex1[j] ];
if ( v1.x < holePoint.x ) {
continue; // on the left of the holePoint
}
float dist = ( v1 - holePoint ).Length();
if ( dist < bestDist ) {
shapeVert = j;
bestDist = dist;
}
}
// connect holeVert to shapeVert
idList< uint16 > vindex;
vindex.SetNum( loopShape.vindex1.Num() + loopHole.vindex1.Num() + 1 );
vindex.SetNum( 0 );
for ( int j = 0; j <= shapeVert; j++ ) {
vindex.Append( loopShape.vindex1[j] );
}
for ( int j = holeVert; j < loopHole.vindex1.Num(); j++ ) {
vindex.Append( loopHole.vindex1[j] );
}
for ( int j = 0; j <= holeVert; j++ ) {
vindex.Append( loopHole.vindex1[j] );
}
for ( int j = shapeVert; j < loopShape.vindex1.Num(); j++ ) {
vindex.Append( loopShape.vindex1[j] );
}
loopShape.vindex1 = vindex;
vindex.Clear();
for ( int j = 0; j <= shapeVert; j++ ) {
vindex.Append( loopShape.vindex2[j] );
}
for ( int j = holeVert; j < loopHole.vindex2.Num(); j++ ) {
vindex.Append( loopHole.vindex2[j] );
}
for ( int j = 0; j <= holeVert; j++ ) {
vindex.Append( loopHole.vindex2[j] );
}
for ( int j = shapeVert; j < loopShape.vindex2.Num(); j++ ) {
vindex.Append( loopShape.vindex2[j] );
}
loopShape.vindex2 = vindex;
fill.loops.RemoveIndexFast( hole );
}
}
}
/*
========================
idSWFShapeParser::TriangulateSoup
========================
*/
void idSWFShapeParser::TriangulateSoup( idSWFShape & shape ) {
MakeLoops();
// Now turn the (potentially) concave line loops into triangles by using ear clipping
shape.fillDraws.SetNum( fillDraws.Num() );
for ( int i = 0; i < fillDraws.Num(); i++ ) {
swfSPDrawFill_t & spDrawFill = fillDraws[i];
idSWFShapeDrawFill & drawFill = shape.fillDraws[i];
swfFillStyle_t & style = spDrawFill.style;
drawFill.style = spDrawFill.style;
for ( int j = 0; j < spDrawFill.loops.Num(); j++ ) {
swfSPLineLoop_t & loop = spDrawFill.loops[j];
int numVerts = loop.vindex1.Num();
for ( int k = 0; k < numVerts - 2; k++ ) {
int v1 = FindEarVert( loop );
if ( v1 == -1 ) {
idLib::Warning( "idSWFShapeParser: could not find an ear vert" );
break;
}
int num = loop.vindex1.Num();
int v2 = ( v1 + 1 ) % num;
int v3 = ( v1 + 2 ) % num;
AddUniqueVert( drawFill, verts[ loop.vindex1[ v1 ] ], verts[ loop.vindex2[ v1 ] ] );
AddUniqueVert( drawFill, verts[ loop.vindex1[ v2 ] ], verts[ loop.vindex2[ v2 ] ] );
AddUniqueVert( drawFill, verts[ loop.vindex1[ v3 ] ], verts[ loop.vindex2[ v3 ] ] );
loop.vindex1.RemoveIndex( v2 );
loop.vindex2.RemoveIndex( v2 );
}
}
}
}
/*
========================
idSWFShapeParser::TriangulateSoup
========================
*/
void idSWFShapeParser::TriangulateSoup( idSWFFontGlyph & shape ) {
MakeLoops();
// Now turn the (potentially) concave line loops into triangles by using ear clipping
assert( fillDraws.Num() == 1 );
swfSPDrawFill_t & spDrawFill = fillDraws[0];
for ( int j = 0; j < spDrawFill.loops.Num(); j++ ) {
swfSPLineLoop_t & loop = spDrawFill.loops[j];
int numVerts = loop.vindex1.Num();
for ( int k = 0; k < numVerts - 2; k++ ) {
int v1 = FindEarVert( loop );
if ( v1 == -1 ) {
idLib::Warning( "idSWFShapeParser: could not find an ear vert" );
break;
}
int num = loop.vindex1.Num();
int v2 = ( v1 + 1 ) % num;
int v3 = ( v1 + 2 ) % num;
shape.indices.Append( shape.verts.AddUnique( verts[ loop.vindex1[ v1 ] ] ) );
shape.indices.Append( shape.verts.AddUnique( verts[ loop.vindex1[ v2 ] ] ) );
shape.indices.Append( shape.verts.AddUnique( verts[ loop.vindex1[ v3 ] ] ) );
loop.vindex1.RemoveIndex( v2 );
loop.vindex2.RemoveIndex( v2 );
}
}
}
struct earVert_t {
int i1;
int i2;
int i3;
float cross;
};
class idSort_Ears : public idSort_Quick< earVert_t, idSort_Ears > {
public:
int Compare( const earVert_t & a, const earVert_t & b ) const {
if ( a.cross < b.cross ) {
return -1;
} else if ( a.cross > b.cross ) {
return 1;
}
return 0;
}
};
/*
========================
idSWFShapeParser::FindEarVert
========================
*/
int idSWFShapeParser::FindEarVert( const swfSPLineLoop_t & loop ) {
assert( loop.vindex1.Num() == loop.vindex2.Num() );
int num = loop.vindex1.Num();
idList<earVert_t> ears;
ears.SetNum( num );
for ( int i1 = 0; i1 < num; i1++ ) {
int i2 = ( i1 + 1 ) % num;
int i3 = ( i1 + 2 ) % num;
const idVec2 & v1s = verts[ loop.vindex1[ i1 ] ];
const idVec2 & v2s = verts[ loop.vindex1[ i2 ] ];
const idVec2 & v3s = verts[ loop.vindex1[ i3 ] ];
idVec2 a = v1s - v2s;
idVec2 b = v2s - v3s;
ears[i1].cross = a.x * b.y - a.y * b.x;
ears[i1].i1 = i1;
ears[i1].i2 = i2;
ears[i1].i3 = i3;
}
ears.SortWithTemplate( idSort_Ears() );
for ( int i = 0; i < ears.Num(); i++ ) {
if ( ears[i].cross < 0.0f ) {
continue;
}
int i1 = ears[i].i1;
int i2 = ears[i].i2;
int i3 = ears[i].i3;
const idVec2 & v1s = verts[ loop.vindex1[ i1 ] ];
const idVec2 & v2s = verts[ loop.vindex1[ i2 ] ];
const idVec2 & v3s = verts[ loop.vindex1[ i3 ] ];
const idVec2 & v1e = verts[ loop.vindex2[ i1 ] ];
const idVec2 & v2e = verts[ loop.vindex2[ i2 ] ];
const idVec2 & v3e = verts[ loop.vindex2[ i3 ] ];
idMat3 edgeEquations1;
edgeEquations1[0].Set( v1s.x, v1s.y, 1.0f );
edgeEquations1[1].Set( v2s.x, v2s.y, 1.0f );
edgeEquations1[2].Set( v3s.x, v3s.y, 1.0f );
idMat3 edgeEquations2;
edgeEquations2[0].Set( v1e.x, v1e.y, 1.0f );
edgeEquations2[1].Set( v2e.x, v2e.y, 1.0f );
edgeEquations2[2].Set( v3e.x, v3e.y, 1.0f );
edgeEquations1.InverseSelf();
edgeEquations2.InverseSelf();
bool isEar = true;
for ( int j = 0; j < num; j++ ) {
if ( j == i1 || j == i2 || j == i3 ) {
continue;
}
idVec3 p1;
p1.ToVec2() = verts[ loop.vindex1[j] ];
p1.z = 1.0f;
idVec3 signs1 = p1 * edgeEquations1;
bool b1x = signs1.x > 0;
bool b1y = signs1.y > 0;
bool b1z = signs1.z > 0;
if ( b1x == b1y && b1x == b1z ) {
// point inside
isEar = false;
break;
}
idVec3 p2;
p2.ToVec2() = verts[ loop.vindex2[j] ];
p2.z = 1.0f;
idVec3 signs2 = p2 * edgeEquations2;
bool b2x = signs2.x > 0;
bool b2y = signs2.y > 0;
bool b2z = signs2.z > 0;
if ( b2x == b2y && b2x == b2z ) {
// point inside
isEar = false;
break;
}
}
if ( isEar ) {
return i1;
}
}
return -1;
}
/*
========================
idSWFShapeParser::AddUniqueVert
========================
*/
void idSWFShapeParser::AddUniqueVert( idSWFShapeDrawFill & drawFill, const idVec2 & start, const idVec2 & end ) {
if ( morph ) {
for ( int i = 0; i < drawFill.startVerts.Num(); i++ ) {
if ( drawFill.startVerts[i] == start && drawFill.endVerts[i] == end ) {
drawFill.indices.Append( i );
return;
}
}
int index1 = drawFill.startVerts.Append( start );
int index2 = drawFill.endVerts.Append( end );
assert( index1 == index2 );
drawFill.indices.Append( index1 );
} else {
drawFill.indices.Append( drawFill.startVerts.AddUnique( start ) );
}
}
/*
========================
idSWFShapeParser::ReadFillStyle
========================
*/
void idSWFShapeParser::ReadFillStyle( idSWFBitStream & bitstream ) {
uint16 fillStyleCount = bitstream.ReadU8();
if ( extendedCount && fillStyleCount == 0xFF ) {
fillStyleCount = bitstream.ReadU16();
}
for ( int i = 0; i < fillStyleCount; i++ ) {
uint8 fillStyleType = bitstream.ReadU8();
swfFillStyle_t & fillStyle = fillDraws.Alloc().style;
fillStyle.type = fillStyleType >> 4;
fillStyle.subType = fillStyleType & 0xF;
if ( fillStyle.type == 0 ) {
if ( morph ) {
bitstream.ReadColorRGBA( fillStyle.startColor );
bitstream.ReadColorRGBA( fillStyle.endColor );
} else {
if ( rgba ) {
bitstream.ReadColorRGBA( fillStyle.startColor );
} else {
bitstream.ReadColorRGB( fillStyle.startColor );
}
fillStyle.endColor = fillStyle.startColor;
}
} else if ( fillStyle.type == 1 ) {
bitstream.ReadMatrix( fillStyle.startMatrix );
if ( morph ) {
bitstream.ReadMatrix( fillStyle.endMatrix );
bitstream.ReadMorphGradient( fillStyle.gradient );
} else {
fillStyle.endMatrix = fillStyle.startMatrix;
bitstream.ReadGradient( fillStyle.gradient, rgba );
}
if ( fillStyle.subType == 3 ) {
assert( morph == false ); // focal gradients aren't allowed in morph shapes
fillStyle.focalPoint = bitstream.ReadFixed8();
}
} else if ( fillStyle.type == 4 ) {
fillStyle.bitmapID = bitstream.ReadU16();
bitstream.ReadMatrix( fillStyle.startMatrix );
if ( morph ) {
bitstream.ReadMatrix( fillStyle.endMatrix );
} else {
fillStyle.endMatrix = fillStyle.startMatrix;
}
}
}
uint16 lineStyleCount = bitstream.ReadU8();
if ( extendedCount && lineStyleCount == 0xFF ) {
lineStyleCount = bitstream.ReadU16();
}
lineDraws.SetNum( lineDraws.Num() + lineStyleCount );
lineDraws.SetNum( 0 );
for ( int i = 0; i < lineStyleCount; i++ ) {
swfLineStyle_t & lineStyle = lineDraws.Alloc().style;
lineStyle.startWidth = bitstream.ReadU16();
if ( lineStyle2 ) {
lineStyle.endWidth = lineStyle.startWidth;
uint8 startCapStyle = bitstream.ReadU( 2 );
uint8 joinStyle = bitstream.ReadU( 2 );
bool hasFillFlag = bitstream.ReadBool();
bool noHScaleFlag = bitstream.ReadBool();
bool noVScaleFlag = bitstream.ReadBool();
bool pixelHintingFlag = bitstream.ReadBool();
uint8 reserved = bitstream.ReadU( 5 );
bool noClose = bitstream.ReadBool();
uint8 endCapStyle = bitstream.ReadU( 2 );
if ( joinStyle == 2 ) {
uint16 miterLimitFactor = bitstream.ReadU16();
}
if ( hasFillFlag ) {
// FIXME: read fill style
idLib::Warning( "idSWFShapeParser: Ignoring hasFillFlag" );
} else {
bitstream.ReadColorRGBA( lineStyle.startColor );
lineStyle.endColor = lineStyle.startColor;
}
} else {
if ( morph ) {
lineStyle.endWidth = bitstream.ReadU16();
} else {
lineStyle.endWidth = lineStyle.startWidth;
}
if ( rgba ) {
bitstream.ReadColorRGBA( lineStyle.startColor );
} else {
bitstream.ReadColorRGB( lineStyle.startColor );
}
if ( morph ) {
bitstream.ReadColorRGBA( lineStyle.endColor );
} else {
lineStyle.endColor = lineStyle.startColor;
}
}
}
}

89
neo/swf/SWF_ShapeParser.h Normal file
View File

@@ -0,0 +1,89 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SHAPEPARSER_H__
#define __SWF_SHAPEPARSER_H__
/*
================================================
This class handles parsing and triangulating a shape
================================================
*/
class idSWFShapeParser {
public:
idSWFShapeParser() { }
void Parse( idSWFBitStream & bitstream, idSWFShape & shape, int recordType );
void ParseMorph( idSWFBitStream & bitstream, idSWFShape & shape );
void ParseFont( idSWFBitStream & bitstream, idSWFFontGlyph & shape );
private:
bool extendedCount;
bool rgba;
bool morph;
bool lineStyle2;
struct swfSPEdge_t {
uint16 v0;
uint16 v1;
uint16 cp; // control point if this is a curve, 0xFFFF otherwise
};
struct swfSPMorphEdge_t {
swfSPEdge_t start;
swfSPEdge_t end;
};
struct swfSPLineLoop_t {
bool hole;
idList< uint16, TAG_SWF > vindex1;
idList< uint16, TAG_SWF > vindex2;
};
struct swfSPDrawFill_t {
swfFillStyle_t style;
idList< swfSPMorphEdge_t, TAG_SWF > edges;
idList< swfSPLineLoop_t, TAG_SWF > loops;
};
struct swfSPDrawLine_t {
swfLineStyle_t style;
idList< swfSPMorphEdge_t, TAG_SWF > edges;
};
idList< idVec2, TAG_SWF > verts;
idList< swfSPDrawFill_t, TAG_SWF > fillDraws;
idList< swfSPDrawLine_t, TAG_SWF > lineDraws;
private:
void ParseShapes( idSWFBitStream & bitstream1, idSWFBitStream * bitstream2, bool swap );
void ReadFillStyle( idSWFBitStream & bitstream );
void ParseEdge( idSWFBitStream & bitstream, int32 & penX, int32 & penY, swfSPEdge_t & edge );
void MakeLoops();
void TriangulateSoup( idSWFShape & shape );
void TriangulateSoup( idSWFFontGlyph & shape );
int FindEarVert( const swfSPLineLoop_t & loop );
void AddUniqueVert( idSWFShapeDrawFill & drawFill, const idVec2 & start, const idVec2 & end );
};
#endif // !__SWF_SHAPEPARSER_H__

110
neo/swf/SWF_Shapes.cpp Normal file
View File

@@ -0,0 +1,110 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
========================
idSWF::DefineShape
========================
*/
void idSWF::DefineShape( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_SHAPE );
if ( entry == NULL ) {
return;
}
idSWFShapeParser swfShapeParser;
swfShapeParser.Parse( bitstream, *entry->shape, 1 );
}
/*
========================
idSWF::DefineShape2
========================
*/
void idSWF::DefineShape2( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_SHAPE );
if ( entry == NULL ) {
return;
}
idSWFShapeParser swfShapeParser;
swfShapeParser.Parse( bitstream, *entry->shape, 2 );
}
/*
========================
idSWF::DefineShape3
========================
*/
void idSWF::DefineShape3( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_SHAPE );
if ( entry == NULL ) {
return;
}
idSWFShapeParser swfShapeParser;
swfShapeParser.Parse( bitstream, *entry->shape, 3 );
}
/*
========================
idSWF::DefineShape4
========================
*/
void idSWF::DefineShape4( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_SHAPE );
if ( entry == NULL ) {
return;
}
idSWFShapeParser swfShapeParser;
swfShapeParser.Parse( bitstream, *entry->shape, 4 );
}
/*
========================
idSWF::DefineMorphShape
========================
*/
void idSWF::DefineMorphShape( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_MORPH );
if ( entry == NULL ) {
return;
}
idSWFShapeParser swfShapeParser;
swfShapeParser.ParseMorph( bitstream, *entry->shape );
}

45
neo/swf/SWF_Sounds.cpp Normal file
View File

@@ -0,0 +1,45 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
========================
idSWF::DefineSound
========================
*/
void idSWF::DefineSound( idSWFBitStream & bitstream ) {
}
/*
========================
idSWFSpriteInstance::StartSound
========================
*/
void idSWFSpriteInstance::StartSound( idSWFBitStream & bitstream ) {
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SPRITEINSTANCE_H__
#define __SWF_SPRITEINSTANCE_H__
/*
================================================
There can be multiple instances of a single sprite running
================================================
*/
class idSWFSpriteInstance {
public:
idSWFSpriteInstance();
~idSWFSpriteInstance();
void Init( idSWFSprite * sprite, idSWFSpriteInstance * parent, int depth );
bool Run();
bool RunActions();
const char * GetName() const { return name.c_str(); }
idSWFScriptObject * GetScriptObject() { return scriptObject; }
void SetAlignment( float x, float y ) { xOffset = x; yOffset = y; }
void SetMaterial( const idMaterial * material, int width = -1, int height = -1 );
void SetVisible( bool visible );
bool IsVisible() { return isVisible; }
void PlayFrame( const idSWFParmList & parms );
void PlayFrame( const char * frameName ) {
idSWFParmList parms;
parms.Append( frameName );
PlayFrame( parms );
}
void PlayFrame( const int frameNum ) {
idSWFParmList parms;
parms.Append( frameNum );
PlayFrame( parms );
}
void StopFrame( const idSWFParmList & parms );
void StopFrame( const char * frameName ) {
idSWFParmList parms;
parms.Append( frameName );
StopFrame( parms );
}
void StopFrame( const int frameNum ) {
idSWFParmList parms;
parms.Append( frameNum );
StopFrame( parms );
}
// FIXME: Why do all the Set functions have defaults of -1.0f? This seems arbitrar.
// Probably better to not have a default at all, so any non-parametized calls throw a
// compilation error.
float GetXPos() const;
float GetYPos( bool overallPos = false ) const;
void SetXPos( float xPos = -1.0f );
void SetYPos( float yPos = -1.0f );
void SetPos( float xPos = -1.0f, float yPos = -1.0f );
void SetAlpha( float val );
void SetScale( float x = -1.0f, float y = -1.0f );
void SetMoveToScale( float x = -1.0f, float y = -1.0f );
bool UpdateMoveToScale( float speed ); // returns true if the update was successful
void SetRotation( float rot );
uint16 GetCurrentFrame() { return currentFrame; }
bool IsPlaying() const { return isPlaying; }
int GetStereoDepth() { return stereoDepth; }
// Removing the private access control statement due to cl 214702
// Apparently MS's C++ compiler supports the newer C++ standard, and GCC supports C++03
// In the new C++ standard, nested members of a friend class have access to private/protected members of the class granting friendship
// In C++03, nested members defined in a friend class do NOT have access to private/protected members of the class granting friendship friend class idSWF;
bool isPlaying;
bool isVisible;
bool childrenRunning;
bool firstRun;
// currentFrame is the frame number currently in the displayList
// we use 1 based frame numbers because currentFrame = 0 means nothing is in the display list
// it's also convenient because Flash also uses 1 based frame numbers
uint16 currentFrame;
uint16 frameCount;
// the sprite this is an instance of
idSWFSprite * sprite;
// sprite instances can be nested
idSWFSpriteInstance * parent;
// depth of this sprite instance in the parent's display list
int depth;
// if this is set, apply this material when rendering any child shapes
int itemIndex;
const idMaterial * materialOverride;
uint16 materialWidth;
uint16 materialHeight;
float xOffset;
float yOffset;
float moveToXScale;
float moveToYScale;
float moveToSpeed;
int stereoDepth;
idSWFScriptObject * scriptObject;
// children display entries
idList< swfDisplayEntry_t, TAG_SWF > displayList;
swfDisplayEntry_t * FindDisplayEntry( int depth );
// name of this sprite instance
idStr name;
struct swfAction_t {
const byte * data;
uint32 dataLength;
};
idList< swfAction_t, TAG_SWF > actions;
idSWFScriptFunction_Script * actionScript;
idSWFScriptVar onEnterFrame;
//idSWFScriptVar onLoad;
// Removing the private access control statement due to cl 214702
// Apparently MS's C++ compiler supports the newer C++ standard, and GCC supports C++03
// In the new C++ standard, nested members of a friend class have access to private/protected members of the class granting friendship
// In C++03, nested members defined in a friend class do NOT have access to private/protected members of the class granting friendship
//----------------------------------
// SWF_PlaceObject.cpp
//----------------------------------
void PlaceObject2( idSWFBitStream & bitstream );
void PlaceObject3( idSWFBitStream & bitstream );
void RemoveObject2( idSWFBitStream & bitstream );
//----------------------------------
// SWF_Sounds.cpp
//----------------------------------
void StartSound( idSWFBitStream & bitstream );
//----------------------------------
// SWF_SpriteInstance.cpp
//----------------------------------
void NextFrame();
void PrevFrame();
void RunTo( int frameNum );
void Play();
void Stop();
void FreeDisplayList();
swfDisplayEntry_t * AddDisplayEntry( int depth, int characterID );
void RemoveDisplayEntry( int depth );
void SwapDepths( int depth1, int depth2 );
void DoAction( idSWFBitStream & bitstream );
idSWFSpriteInstance * FindChildSprite( const char * childName );
idSWFSpriteInstance * ResolveTarget( const char * targetName );
uint32 FindFrame( const char * frameLabel ) const;
bool FrameExists( const char * frameLabel ) const;
bool IsBetweenFrames( const char * frameLabel1, const char * frameLabel2 ) const;
};
/*
================================================
This is the prototype object that all the sprite instance script objects reference
================================================
*/
class idSWFScriptObject_SpriteInstancePrototype : public idSWFScriptObject {
public:
idSWFScriptObject_SpriteInstancePrototype();
#define SWF_SPRITE_FUNCTION_DECLARE( x ) \
class idSWFScriptFunction_##x : public idSWFScriptFunction { \
public: \
void AddRef() {} \
void Release() {} \
idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ); \
} scriptFunction_##x
SWF_SPRITE_FUNCTION_DECLARE( duplicateMovieClip );
SWF_SPRITE_FUNCTION_DECLARE( gotoAndPlay );
SWF_SPRITE_FUNCTION_DECLARE( gotoAndStop );
SWF_SPRITE_FUNCTION_DECLARE( swapDepths );
SWF_SPRITE_FUNCTION_DECLARE( nextFrame );
SWF_SPRITE_FUNCTION_DECLARE( prevFrame );
SWF_SPRITE_FUNCTION_DECLARE( play );
SWF_SPRITE_FUNCTION_DECLARE( stop );
SWF_NATIVE_VAR_DECLARE( _x );
SWF_NATIVE_VAR_DECLARE( _y );
SWF_NATIVE_VAR_DECLARE( _xscale );
SWF_NATIVE_VAR_DECLARE( _yscale );
SWF_NATIVE_VAR_DECLARE( _alpha );
SWF_NATIVE_VAR_DECLARE( _brightness );
SWF_NATIVE_VAR_DECLARE( _visible );
SWF_NATIVE_VAR_DECLARE( _width );
SWF_NATIVE_VAR_DECLARE( _height );
SWF_NATIVE_VAR_DECLARE( _rotation );
SWF_NATIVE_VAR_DECLARE_READONLY( _name );
SWF_NATIVE_VAR_DECLARE_READONLY( _currentframe );
SWF_NATIVE_VAR_DECLARE_READONLY( _totalframes );
SWF_NATIVE_VAR_DECLARE_READONLY( _target );
SWF_NATIVE_VAR_DECLARE_READONLY( _framesloaded );
SWF_NATIVE_VAR_DECLARE_READONLY( _droptarget );
SWF_NATIVE_VAR_DECLARE_READONLY( _url );
SWF_NATIVE_VAR_DECLARE_READONLY( _highquality );
SWF_NATIVE_VAR_DECLARE_READONLY( _focusrect );
SWF_NATIVE_VAR_DECLARE_READONLY( _soundbuftime );
SWF_NATIVE_VAR_DECLARE_READONLY( _quality );
SWF_NATIVE_VAR_DECLARE_READONLY( _mousex );
SWF_NATIVE_VAR_DECLARE_READONLY( _mousey );
SWF_NATIVE_VAR_DECLARE( _stereoDepth );
SWF_NATIVE_VAR_DECLARE( _itemindex );
SWF_NATIVE_VAR_DECLARE( material );
SWF_NATIVE_VAR_DECLARE( materialWidth );
SWF_NATIVE_VAR_DECLARE( materialHeight );
SWF_NATIVE_VAR_DECLARE( xOffset );
SWF_NATIVE_VAR_DECLARE( onEnterFrame );
//SWF_NATIVE_VAR_DECLARE( onLoad );
};
#endif

257
neo/swf/SWF_Sprites.cpp Normal file
View File

@@ -0,0 +1,257 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
/*
========================
idSWFSprite::idSWFSprite
========================
*/
idSWFSprite::idSWFSprite( idSWF * _swf ) :
frameCount( 0 ),
swf( _swf ),
commandBuffer( NULL )
{
}
/*
========================
idSWFSprite::~idSWFSprite
========================
*/
idSWFSprite::~idSWFSprite() {
Mem_Free( commandBuffer );
}
/*
========================
idSWF::DefineSprite
========================
*/
void idSWF::DefineSprite( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_SPRITE );
if ( entry == NULL ) {
return;
}
entry->sprite->Load( bitstream, false );
}
/*
========================
idSWFSprite::Load
========================
*/
void idSWFSprite::Load( idSWFBitStream & bitstream, bool parseDictionary ) {
frameCount = bitstream.ReadU16();
// run through the file once, building the dictionary and accumulating control tags
frameOffsets.SetNum( frameCount + 1 );
frameOffsets[0] = 0;
unsigned int currentFrame = 1;
while ( true ) {
uint16 codeAndLength = bitstream.ReadU16();
uint32 recordLength = ( codeAndLength & 0x3F );
if ( recordLength == 0x3F ) {
recordLength = bitstream.ReadU32();
}
idSWFBitStream tagStream( bitstream.ReadData( recordLength ), recordLength, false );
swfTag_t tag = (swfTag_t)( codeAndLength >> 6 );
// ----------------------
// Definition tags
// definition tags are only allowed in the main sprite
// ----------------------
if ( parseDictionary ) {
bool handled = true;
switch ( tag ) {
#define HANDLE_SWF_TAG( x ) case Tag_##x: swf->x( tagStream ); break;
HANDLE_SWF_TAG( JPEGTables );
HANDLE_SWF_TAG( DefineBits );
HANDLE_SWF_TAG( DefineBitsJPEG2 );
HANDLE_SWF_TAG( DefineBitsJPEG3 );
HANDLE_SWF_TAG( DefineBitsLossless );
HANDLE_SWF_TAG( DefineBitsLossless2 );
HANDLE_SWF_TAG( DefineShape );
HANDLE_SWF_TAG( DefineShape2 );
HANDLE_SWF_TAG( DefineShape3 );
HANDLE_SWF_TAG( DefineShape4 );
HANDLE_SWF_TAG( DefineSprite );
HANDLE_SWF_TAG( DefineSound );
//HANDLE_SWF_TAG( DefineMorphShape ); // these don't work right
HANDLE_SWF_TAG( DefineFont2 );
HANDLE_SWF_TAG( DefineFont3 );
HANDLE_SWF_TAG( DefineText );
HANDLE_SWF_TAG( DefineText2 );
HANDLE_SWF_TAG( DefineEditText );
#undef HANDLE_SWF_TAG
default: handled = false;
}
if ( handled ) {
continue;
}
}
// ----------------------
// Control tags
// control tags are stored off in the commands list and processed at run time
// except for a couple really special control tags like "End" and "FrameLabel"
// ----------------------
switch ( tag ) {
case Tag_End:
return;
case Tag_ShowFrame:
frameOffsets[ currentFrame ] = commands.Num();
currentFrame++;
break;
case Tag_FrameLabel: {
swfFrameLabel_t & label = frameLabels.Alloc();
label.frameNum = currentFrame;
label.frameLabel = tagStream.ReadString();
}
break;
case Tag_DoInitAction: {
tagStream.ReadU16();
idSWFBitStream &initaction = doInitActions.Alloc();
initaction.Load( tagStream.ReadData( recordLength - 2 ), recordLength - 2, true );
}
break;
case Tag_DoAction:
case Tag_PlaceObject2:
case Tag_PlaceObject3:
case Tag_RemoveObject2: {
swfSpriteCommand_t & command = commands.Alloc();
command.tag = tag;
command.stream.Load( tagStream.ReadData( recordLength ), recordLength, true );
}
break;
default:
// We don't care, about sprite tags we don't support ... RobA
//idLib::Printf( "Load Sprite: Unhandled tag %s\n", idSWF::GetTagName( tag ) );
break;
}
}
}
/*
========================
idSWFSprite::Read
========================
*/
void idSWFSprite::Read( idFile * f ) {
int num = 0;
f->ReadBig( frameCount );
f->ReadBig( num ); frameOffsets.SetNum( num );
f->ReadBigArray( frameOffsets.Ptr(), frameOffsets.Num() );
f->ReadBig( num ); frameLabels.SetNum( num );
for ( int i = 0; i < frameLabels.Num(); i++ ) {
f->ReadBig( frameLabels[i].frameNum );
f->ReadString( frameLabels[i].frameLabel );
}
uint32 bufferSize;
f->ReadBig( bufferSize );
commandBuffer = (byte *)Mem_Alloc( bufferSize, TAG_SWF );
f->Read( commandBuffer, bufferSize );
byte * currentBuffer = commandBuffer;
f->ReadBig( num ); commands.SetNum( num );
for ( int i = 0; i < commands.Num(); i++ ) {
uint32 streamLength = 0;
f->ReadBig( commands[i].tag );
f->ReadBig( streamLength );
commands[i].stream.Load( currentBuffer, streamLength, false );
currentBuffer += streamLength;
}
uint32 doInitActionLength = 0;
f->ReadBig( num );
doInitActions.SetNum( num );
for ( int i = 0; i < num; i++ ) {
f->ReadBig( doInitActionLength );
idSWFBitStream &initaction = doInitActions[i];
initaction.Load( currentBuffer, doInitActionLength, true );
currentBuffer += doInitActionLength;
}
}
/*
========================
idSWFSprite::Write
========================
*/
void idSWFSprite::Write( idFile * f ) {
f->WriteBig( frameCount );
f->WriteBig( frameOffsets.Num() );
f->WriteBigArray( frameOffsets.Ptr(), frameOffsets.Num() );
f->WriteBig( frameLabels.Num() );
for ( int i = 0; i < frameLabels.Num(); i++ ) {
f->WriteBig( frameLabels[i].frameNum );
f->WriteString( frameLabels[i].frameLabel );
}
uint32 totalLength = 0;
for ( int i = 0; i < commands.Num(); i++ ) {
totalLength += commands[i].stream.Length();
}
for (int i = 0; i < doInitActions.Num(); i++ ) {
totalLength += doInitActions[i].Length();
}
f->WriteBig( totalLength );
for ( int i = 0; i < commands.Num(); i++ ) {
f->Write( commands[i].stream.Ptr(), commands[i].stream.Length() );
}
for ( int i = 0; i < doInitActions.Num(); i++ ){
f->Write( doInitActions[i].Ptr(), doInitActions[i].Length() );
}
f->WriteBig( commands.Num() );
for ( int i = 0; i < commands.Num(); i++ ) {
f->WriteBig( commands[i].tag );
f->WriteBig( commands[i].stream.Length() );
}
f->WriteBig( doInitActions.Num() );
for ( int i = 0; i < doInitActions.Num(); i++ ){
f->WriteBig( doInitActions[i].Length() );
}
}

81
neo/swf/SWF_Sprites.h Normal file
View File

@@ -0,0 +1,81 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_SPRITES_H__
#define __SWF_SPRITES_H__
/*
================================================
What the swf file format calls a "sprite" is known as a "movie clip" in Flash
There is one main sprite, and many many sub-sprites
Only the main sprite is allowed to add things to the dictionary
================================================
*/
class idSWFSprite {
public:
idSWFSprite( class idSWF * swf );
~idSWFSprite();
void Load( idSWFBitStream & bitstream, bool parseDictionary );
void Read( idFile * f );
void Write( idFile * f );
class idSWF * GetSWF() { return swf; }
private:
friend class idSWFSpriteInstance;
friend class idSWFScriptFunction_Script;
class idSWF * swf; // this is required so things can access the dictionary, it would be kind of nice if we just had an idSWFDictionary pointer instead
uint16 frameCount;
// frameOffsets contains offsets into the commands list for each frame
// the first command for frame 3 is frameOffsets[2] and the last command is frameOffsets[3]
idList< uint32, TAG_SWF > frameOffsets;
struct swfFrameLabel_t {
idStr frameLabel;
uint32 frameNum;
};
idList< swfFrameLabel_t, TAG_SWF > frameLabels;
struct swfSpriteCommand_t {
swfTag_t tag;
idSWFBitStream stream;
};
idList< swfSpriteCommand_t, TAG_SWF > commands;
//// [ES-BrianBugh 1/16/10] - There can be multiple DoInitAction tags, and all need to be executed.
idList<idSWFBitStream, TAG_SWF> doInitActions;
byte * commandBuffer;
};
#endif // !__SWF_SPRITES_H__

306
neo/swf/SWF_Text.cpp Normal file
View File

@@ -0,0 +1,306 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#pragma warning( disable: 4189 ) // local variable is initialized but not referenced
/*
========================
idSWF::DefineFont2
========================
*/
void idSWF::DefineFont2( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_FONT );
if ( entry == NULL ) {
return;
}
uint8 flags = bitstream.ReadU8();
uint8 language = bitstream.ReadU8();
char fontName[257];
uint8 fontNameLength = bitstream.ReadU8();
memcpy( fontName, bitstream.ReadData( fontNameLength ), fontNameLength );
fontName[ fontNameLength ] = 0;
entry->font->fontID = renderSystem->RegisterFont( fontName );
uint16 numGlyphs = bitstream.ReadU16();
entry->font->glyphs.SetNum( numGlyphs );
if ( flags & BIT( 3 ) ) {
// 32 bit offsets
uint32 offsetTableSize = ( numGlyphs + 1 ) * 4;
idSWFBitStream offsetStream( bitstream.ReadData( offsetTableSize ), offsetTableSize, false );
if ( offsetStream.ReadU32() != offsetTableSize ) {
idLib::Warning( "idSWF::DefineFont2: first glyph offset != offsetTableSize" );
return;
}
uint32 previousOffset = offsetTableSize;
for ( int i = 0; i < numGlyphs; i++ ) {
uint32 nextOffset = offsetStream.ReadU32();
uint32 shapeSize = nextOffset - previousOffset;
previousOffset = nextOffset;
idSWFBitStream shapeStream( bitstream.ReadData( shapeSize ), shapeSize, false );
idSWFShapeParser swfShapeParser;
swfShapeParser.ParseFont( shapeStream, entry->font->glyphs[i] );
}
} else {
// 16 bit offsets
uint16 offsetTableSize = ( numGlyphs + 1 ) * 2;
idSWFBitStream offsetStream( bitstream.ReadData( offsetTableSize ), offsetTableSize, false );
if ( offsetStream.ReadU16() != offsetTableSize ) {
idLib::Warning( "idSWF::DefineFont2: first glyph offset != offsetTableSize" );
return;
}
uint16 previousOffset = offsetTableSize;
for ( int i = 0; i < numGlyphs; i++ ) {
uint16 nextOffset = offsetStream.ReadU16();
uint16 shapeSize = nextOffset - previousOffset;
previousOffset = nextOffset;
idSWFBitStream shapeStream( bitstream.ReadData( shapeSize ), shapeSize, false );
idSWFShapeParser swfShapeParser;
swfShapeParser.ParseFont( shapeStream, entry->font->glyphs[i] );
}
}
if ( flags & BIT( 2 ) ) {
// 16 bit codes
for ( int i = 0; i < numGlyphs; i++ ) {
entry->font->glyphs[i].code = bitstream.ReadU16();
}
} else {
// 8 bit codes
for ( int i = 0; i < numGlyphs; i++ ) {
entry->font->glyphs[i].code = bitstream.ReadU8();
}
}
if ( flags & BIT( 7 ) ) {
entry->font->ascent = bitstream.ReadS16();
entry->font->descent = bitstream.ReadS16();
entry->font->leading = bitstream.ReadS16();
for ( int i = 0; i < numGlyphs; i++ ) {
entry->font->glyphs[i].advance = bitstream.ReadS16();
}
for ( int i = 0; i < numGlyphs; i++ ) {
swfRect_t ignored;
bitstream.ReadRect( ignored );
}
uint16 kearningCount = bitstream.ReadU16();
if ( flags & BIT( 2 ) ) {
for ( int i = 0; i < kearningCount; i++ ) {
uint16 code1 = bitstream.ReadU16();
uint16 code2 = bitstream.ReadU16();
int16 adjustment = bitstream.ReadS16();
}
} else {
for ( int i = 0; i < kearningCount; i++ ) {
uint16 code1 = bitstream.ReadU8();
uint16 code2 = bitstream.ReadU8();
int16 adjustment = bitstream.ReadS16();
}
}
}
}
/*
========================
idSWF::DefineFont3
========================
*/
void idSWF::DefineFont3( idSWFBitStream & bitstream ) {
DefineFont2( bitstream );
}
/*
========================
idSWF::DefineTextX
========================
*/
void idSWF::DefineTextX( idSWFBitStream & bitstream, bool rgba ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_TEXT );
if ( entry == NULL ) {
return;
}
idSWFText * text = entry->text;
bitstream.ReadRect( text->bounds );
bitstream.ReadMatrix( text->matrix );
uint8 glyphBits = bitstream.ReadU8();
uint8 advanceBits = bitstream.ReadU8();
while ( true ) {
uint8 flags = bitstream.ReadU8();
if ( flags == 0 ) {
break;
}
idSWFTextRecord & textRecord = text->textRecords.Alloc();
if ( flags & BIT( 3 ) ) {
textRecord.fontID = bitstream.ReadU16();
}
if ( flags & BIT( 2 ) ) {
if ( rgba ) {
bitstream.ReadColorRGBA( textRecord.color );
} else {
bitstream.ReadColorRGB( textRecord.color );
}
}
if ( flags & BIT( 0 ) ) {
textRecord.xOffset = bitstream.ReadS16();
}
if ( flags & BIT( 1 ) ) {
textRecord.yOffset = bitstream.ReadS16();
}
if ( flags & BIT( 3 ) ) {
textRecord.textHeight = bitstream.ReadU16();
}
textRecord.firstGlyph = text->glyphs.Num();
textRecord.numGlyphs = bitstream.ReadU8();
for ( int i = 0; i < textRecord.numGlyphs; i++ ) {
swfGlyphEntry_t & glyph = text->glyphs.Alloc();
glyph.index = bitstream.ReadU( glyphBits );
glyph.advance = bitstream.ReadS( advanceBits );
}
};
}
/*
========================
idSWF::DefineText
========================
*/
void idSWF::DefineText( idSWFBitStream & bitstream ) {
DefineTextX( bitstream, false );
}
/*
========================
idSWF::DefineText2
========================
*/
void idSWF::DefineText2( idSWFBitStream & bitstream ) {
DefineTextX( bitstream, true );
}
/*
========================
idSWF::DefineEditText
========================
*/
void idSWF::DefineEditText( idSWFBitStream & bitstream ) {
uint16 characterID = bitstream.ReadU16();
idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_EDITTEXT );
if ( entry == NULL ) {
return;
}
idSWFEditText * edittext = entry->edittext;
bitstream.ReadRect( edittext->bounds );
bitstream.ResetBits();
bool hasText = bitstream.ReadBool();
bool wordWrap = bitstream.ReadBool();
bool multiline = bitstream.ReadBool();
bool password = bitstream.ReadBool();
bool readonly = bitstream.ReadBool();
bool hasTextColor = bitstream.ReadBool();
bool hasMaxLength = bitstream.ReadBool();
bool hasFont = bitstream.ReadBool();
bool hasFontClass = bitstream.ReadBool();
bool autoSize = bitstream.ReadBool();
bool hasLayout = bitstream.ReadBool();
bool noSelect = bitstream.ReadBool();
bool border = bitstream.ReadBool();
bool wasStatic = bitstream.ReadBool();
bool html = bitstream.ReadBool();
bool useOutlines = bitstream.ReadBool();
if ( hasFont ) {
edittext->fontID = bitstream.ReadU16();
edittext->fontHeight = bitstream.ReadU16();
}
if ( hasFontClass ) {
idStr fontClass = bitstream.ReadString();
}
if ( hasTextColor ) {
bitstream.ReadColorRGBA( edittext->color );
}
if ( hasMaxLength ) {
edittext->maxLength = bitstream.ReadU16();
}
if ( hasLayout ) {
edittext->align = (swfEditTextAlign_t)bitstream.ReadU8();
edittext->leftMargin = bitstream.ReadU16();
edittext->rightMargin = bitstream.ReadU16();
edittext->indent = bitstream.ReadU16();
edittext->leading = bitstream.ReadS16();
}
edittext->variable = bitstream.ReadString();
if ( hasText ) {
const char * text = bitstream.ReadString();
idStr initialText;
// convert html tags if necessary
for ( int i = 0; text[i] != 0; i++ ) {
if ( text[i] == '<' ) {
if ( i != 0 && text[i+1] == 'p' ) {
initialText.Append( '\n' );
}
for ( ; text[i] != 0 && text[i] != '>'; i++ ) {
}
continue;
}
byte tc = (byte)text[i];
if ( tc == '&' ) {
idStr special;
for ( i++; text[i] != 0 && text[i] != ';'; i++ ) {
special.Append( text[i] );
}
if ( special.Icmp( "amp" ) == 0 ) {
tc = '&';
} else if ( special.Icmp( "apos" ) == 0 ) {
tc = '\'';
} else if ( special.Icmp( "lt" ) == 0 ) {
tc = '<';
} else if ( special.Icmp( "gt" ) == 0 ) {
tc = '>';
} else if ( special.Icmp( "quot" ) == 0 ) {
tc = '\"';
}
}
initialText.Append( tc );
}
edittext->initialText = initialText;
}
edittext->flags |= wordWrap ? SWF_ET_WORDWRAP : 0;
edittext->flags |= multiline ? SWF_ET_MULTILINE : 0;
edittext->flags |= password ? SWF_ET_PASSWORD : 0;
edittext->flags |= readonly ? SWF_ET_READONLY : 0;
edittext->flags |= autoSize ? SWF_ET_AUTOSIZE : 0;
edittext->flags |= border ? SWF_ET_BORDER : 0;
}

1242
neo/swf/SWF_TextInstance.cpp Normal file

File diff suppressed because it is too large Load Diff

251
neo/swf/SWF_TextInstance.h Normal file
View File

@@ -0,0 +1,251 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_TEXTINSTANCE_H__
#define __SWF_TEXTINSTANCE_H__
struct subTimingWordData_t {
subTimingWordData_t() {
startTime = 0;
forceBreak = false;
}
idStr phrase;
int startTime;
bool forceBreak;
};
class idSWFTextInstance {
public:
idSWFTextInstance();
~idSWFTextInstance();
void Init( idSWFEditText * editText, idSWF * _swf );
idSWFScriptObject * GetScriptObject() { return &scriptObject; }
bool GetHasDropShadow() { return useDropShadow; }
bool HasStroke() { return useStroke; }
float GetStrokeStrength() { return strokeStrength; }
float GetStrokeWeight() { return strokeWeight; }
// used for when text has random render mode set
bool IsGeneratingRandomText() { return generatingText; }
void StartRandomText( int time );
idStr GetRandomText( int time );
void StartParagraphText( int time );
idStr GetParagraphText( int time );
bool NeedsGenerateRandomText() { return triggerGenerate; }
bool NeedsSoundPlayed();
void ClearPlaySound() { needsSoundUpdate = false; }
idStr GetSoundClip() { return soundClip; }
void SetIgnoreColor( bool ignore ) { ignoreColor = ignore; }
void SetStrokeInfo( bool use, float strength = 0.75f, float weight = 1.75f );
int CalcMaxScroll( int numLines = -1 );
int CalcNumLines();
// subtitle functions
void SwitchSubtitleText( int time );
bool UpdateSubtitle( int time );
bool IsSubtitle() { return isSubtitle; }
bool IsUpdatingSubtitle() { return subUpdating; }
void SetSubEndIndex( int endChar, int time );
int GetLastWordIndex() { return subLastWordIndex; }
int GetPrevLastWordIndex() { return subPrevLastWordIndex; }
void LastWordChanged( int wordCount, int time );
void SetSubStartIndex( int value ) { subCharStartIndex = value; }
int GetSubEndIndex() { return subCharEndIndex; }
int GetSubStartIndex() { return subCharStartIndex; }
void SetSubNextStartIndex( int value );
int GetApporoximateSubtitleBreak( int time );
bool SubNeedsSwitch() { return subNeedsSwitch; }
idStr GetPreviousText() { return subtitleText.c_str(); }
void SubtitleComplete();
int GetSubAlignment() { return subAlign; }
idStr GetSpeaker() { return subSpeaker.c_str(); }
void SubtitleCleanup();
float GetTextLength();
int GetInputStartChar( ) { return inputTextStartChar; }
void SetInputStartCharacter( int c ) { inputTextStartChar = c; }
const idSWFEditText * GetEditText() const { return editText; }
void SetText( idStr val ) { text = val; lengthCalculated = false; }
// Removing the private access control statement due to cl 214702
// Apparently MS's C++ compiler supports the newer C++ standard, and GCC supports C++03
// In the new C++ standard, nested members of a friend class have access to private/protected members of the class granting friendship
// In C++03, nested members defined in a friend class do NOT have access to private/protected members of the class granting friendship
idSWFEditText * editText;
idSWF * swf;
// this text instance's script object
idSWFScriptObject scriptObject;
idStr text;
idStr randomtext;
idStr variable;
swfColorRGBA_t color;
bool visible;
bool tooltip;
int selectionStart;
int selectionEnd;
bool ignoreColor;
int scroll;
int scrollTime;
int maxscroll;
int maxLines;
float glyphScale;
swfRect_t bounds;
float linespacing;
bool shiftHeld;
int lastInputTime;
bool useDropShadow;
bool useStroke;
float strokeStrength;
float strokeWeight;
int textLength;
bool lengthCalculated;
swfTextRenderMode_t renderMode;
bool generatingText;
int rndSpotsVisible;
int rndSpacesVisible;
int charMultiplier;
int textSpotsVisible;
int rndTime;
int startRndTime;
int prevReplaceIndex;
bool triggerGenerate;
int renderDelay;
bool scrollUpdate;
idStr soundClip;
bool needsSoundUpdate;
idList<int, TAG_SWF> indexArray;
idRandom2 rnd;
// used for subtitles
bool isSubtitle;
int subLength;
int subCharDisplayTime;
int subAlign;
bool subUpdating;
int subCharStartIndex;
int subNextStartIndex;
int subCharEndIndex;
int subDisplayTime;
int subStartTime;
int subSourceID;
idStr subtitleText;
bool subNeedsSwitch;
bool subForceKillQueued;
bool subForceKill;
int subKillTimeDelay;
int subSwitchTime;
int subLastWordIndex;
int subPrevLastWordIndex;
idStr subSpeaker;
bool subWaitClear;
bool subInitialLine;
// input text
int inputTextStartChar;
idList< subTimingWordData_t, TAG_SWF > subtitleTimingInfo;
};
/*
================================================
This is the prototype object that all the text instance script objects reference
================================================
*/
class idSWFScriptObject_TextInstancePrototype : public idSWFScriptObject {
public:
idSWFScriptObject_TextInstancePrototype();
//----------------------------------
// Native Script Functions
//----------------------------------
#define SWF_TEXT_FUNCTION_DECLARE( x ) \
class idSWFScriptFunction_##x : public idSWFScriptFunction_RefCounted { \
public: \
void AddRef() {} \
void Release() {} \
idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ); \
} scriptFunction_##x;
SWF_TEXT_FUNCTION_DECLARE( onKey );
SWF_TEXT_FUNCTION_DECLARE( onChar );
SWF_TEXT_FUNCTION_DECLARE( generateRnd );
SWF_TEXT_FUNCTION_DECLARE( calcNumLines );
SWF_NATIVE_VAR_DECLARE( text );
SWF_NATIVE_VAR_DECLARE( autoSize );
SWF_NATIVE_VAR_DECLARE( dropShadow );
SWF_NATIVE_VAR_DECLARE( _stroke );
SWF_NATIVE_VAR_DECLARE( _strokeStrength );
SWF_NATIVE_VAR_DECLARE( _strokeWeight );
SWF_NATIVE_VAR_DECLARE( variable );
SWF_NATIVE_VAR_DECLARE( _alpha );
SWF_NATIVE_VAR_DECLARE( textColor );
SWF_NATIVE_VAR_DECLARE( _visible );
SWF_NATIVE_VAR_DECLARE( scroll );
SWF_NATIVE_VAR_DECLARE( maxscroll );
SWF_NATIVE_VAR_DECLARE( selectionStart );
SWF_NATIVE_VAR_DECLARE( selectionEnd );
SWF_NATIVE_VAR_DECLARE( isTooltip );
SWF_NATIVE_VAR_DECLARE( mode );
SWF_NATIVE_VAR_DECLARE( delay );
SWF_NATIVE_VAR_DECLARE( renderSound );
SWF_NATIVE_VAR_DECLARE( updateScroll );
SWF_NATIVE_VAR_DECLARE( subtitle );
SWF_NATIVE_VAR_DECLARE( subtitleAlign );
SWF_NATIVE_VAR_DECLARE( subtitleSourceID );
SWF_NATIVE_VAR_DECLARE( subtitleSpeaker );
SWF_NATIVE_VAR_DECLARE_READONLY( _textLength );
SWF_TEXT_FUNCTION_DECLARE( subtitleSourceCheck );
SWF_TEXT_FUNCTION_DECLARE( subtitleStart );
SWF_TEXT_FUNCTION_DECLARE( subtitleLength );
SWF_TEXT_FUNCTION_DECLARE( killSubtitle );
SWF_TEXT_FUNCTION_DECLARE( forceKillSubtitle );
SWF_TEXT_FUNCTION_DECLARE( subLastLine );
SWF_TEXT_FUNCTION_DECLARE( addSubtitleInfo );
SWF_TEXT_FUNCTION_DECLARE( terminateSubtitle );
SWF_TEXT_FUNCTION_DECLARE( clearTimingInfo );
};
#endif // !__SWF_TEXTINSTANCE_H__

410
neo/swf/SWF_Types.h Normal file
View File

@@ -0,0 +1,410 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SWF_TYPES1_H__
#define __SWF_TYPES1_H__
ID_INLINE float SWFTWIP( int twip ) { return twip * ( 1.0f / 20.0f ); }
ID_INLINE float SWFFIXED16( int fixed ) { return fixed * ( 1.0f / 65536.0f ); }
ID_INLINE float SWFFIXED8( int fixed ) { return fixed * ( 1.0f / 256.0f ); }
struct swfHeader_t {
byte compression;
byte W;
byte S;
byte version;
uint32 fileLength;
};
struct swfRect_t {
swfRect_t();
idVec2 tl;
idVec2 br;
};
struct swfMatrix_t {
swfMatrix_t();
float xx, yy;
float xy, yx;
float tx, ty;
idVec2 Scale( const idVec2 & in ) const;
idVec2 Transform( const idVec2 & in ) const;
swfMatrix_t Multiply( const swfMatrix_t & a ) const;
swfMatrix_t Inverse() const;
swfMatrix_t & operator=( const swfMatrix_t & a ) { xx = a.xx; yy = a.yy; xy = a.xy; yx = a.yx; tx = a.tx; ty = a.ty; return *this; }
};
struct swfColorRGB_t {
swfColorRGB_t();
idVec4 ToVec4() const;
uint8 r, g, b;
};
struct swfColorRGBA_t : public swfColorRGB_t {
swfColorRGBA_t();
idVec4 ToVec4() const;
uint8 a;
};
struct swfLineStyle_t {
swfLineStyle_t();
uint16 startWidth;
uint16 endWidth;
swfColorRGBA_t startColor;
swfColorRGBA_t endColor;
};
struct swfGradientRecord_t {
swfGradientRecord_t();
uint8 startRatio;
uint8 endRatio;
swfColorRGBA_t startColor;
swfColorRGBA_t endColor;
};
struct swfGradient_t {
swfGradient_t();
uint8 numGradients;
swfGradientRecord_t gradientRecords[ 16 ];
};
struct swfFillStyle_t {
swfFillStyle_t();
uint8 type; // 0 = solid, 1 = gradient, 4 = bitmap
uint8 subType; // 0 = linear, 2 = radial, 3 = focal; 0 = repeat, 1 = clamp, 2 = near repeat, 3 = near clamp
swfColorRGBA_t startColor; // if type = 0
swfColorRGBA_t endColor; // if type = 0
swfMatrix_t startMatrix; // if type > 0
swfMatrix_t endMatrix; // if type > 0
swfGradient_t gradient; // if type = 1
float focalPoint; // if type = 1 and subType = 3
uint16 bitmapID; // if type = 4
};
class idSWFShapeDrawFill {
public:
swfFillStyle_t style;
idList< idVec2, TAG_SWF > startVerts;
idList< idVec2, TAG_SWF > endVerts;
idList< uint16, TAG_SWF > indices;
};
class idSWFShapeDrawLine {
public:
swfLineStyle_t style;
idList< idVec2, TAG_SWF > startVerts;
idList< idVec2, TAG_SWF > endVerts;
idList< uint16, TAG_SWF > indices;
};
class idSWFShape {
public:
~idSWFShape() {
fillDraws.Clear();
lineDraws.Clear();
}
swfRect_t startBounds;
swfRect_t endBounds;
idList< idSWFShapeDrawFill, TAG_SWF > fillDraws;
idList< idSWFShapeDrawLine, TAG_SWF > lineDraws;
};
class idSWFFontGlyph {
public:
idSWFFontGlyph();
uint16 code;
int16 advance;
idList< idVec2, TAG_SWF > verts;
idList< uint16, TAG_SWF > indices;
};
class idSWFFont {
public:
idSWFFont();
class idFont * fontID;
int16 ascent;
int16 descent;
int16 leading;
idList< idSWFFontGlyph, TAG_SWF > glyphs;
};
class idSWFTextRecord {
public:
idSWFTextRecord();
uint16 fontID;
swfColorRGBA_t color;
int16 xOffset;
int16 yOffset;
uint16 textHeight;
uint16 firstGlyph;
uint8 numGlyphs;
};
struct swfGlyphEntry_t {
swfGlyphEntry_t();
uint32 index;
int32 advance;
};
class idSWFText {
public:
swfRect_t bounds;
swfMatrix_t matrix;
idList< idSWFTextRecord, TAG_SWF > textRecords;
idList< swfGlyphEntry_t, TAG_SWF > glyphs;
};
enum swfEditTextFlags_t {
SWF_ET_NONE = 0,
SWF_ET_WORDWRAP = BIT(0),
SWF_ET_MULTILINE = BIT(1),
SWF_ET_PASSWORD = BIT(2),
SWF_ET_READONLY = BIT(3),
SWF_ET_AUTOSIZE = BIT(4),
SWF_ET_BORDER = BIT(5),
};
enum swfEditTextAlign_t {
SWF_ET_ALIGN_LEFT,
SWF_ET_ALIGN_RIGHT,
SWF_ET_ALIGN_CENTER,
SWF_ET_ALIGN_JUSTIFY
};
enum swfTextRenderMode_t {
SWF_TEXT_RENDER_NORMAL = 0,
SWF_TEXT_RENDER_RANDOM_APPEAR,
SWF_TEXT_RENDER_RANDOM_APPEAR_CAPS,
SWF_TEXT_RENDER_PARAGRAPH,
SWF_TEXT_RENDER_AUTOSCROLL,
SWF_TEXT_RENDER_MODE_COUNT,
};
class idSWFEditText {
public:
idSWFEditText();
swfRect_t bounds;
uint32 flags;
uint16 fontID;
uint16 fontHeight;
swfColorRGBA_t color;
uint16 maxLength;
swfEditTextAlign_t align;
uint16 leftMargin;
uint16 rightMargin;
uint16 indent;
int16 leading;
idStr variable;
idStr initialText;
};
struct swfColorXform_t {
swfColorXform_t();
idVec4 mul;
idVec4 add;
swfColorXform_t Multiply( const swfColorXform_t & a ) const;
swfColorXform_t & operator=( const swfColorXform_t & a ) { mul = a.mul; add = a.add; return *this; }
};
struct swfDisplayEntry_t {
swfDisplayEntry_t();
uint16 characterID;
uint16 depth;
uint16 clipDepth;
uint16 blendMode;
swfMatrix_t matrix;
swfColorXform_t cxf;
float ratio;
// if this entry is a sprite, then this will point to the specific instance of that sprite
class idSWFSpriteInstance * spriteInstance;
// if this entry is text, then this will point to the specific instance of the text
class idSWFTextInstance * textInstance;
};
struct swfRenderState_t {
swfRenderState_t();
swfMatrix_t matrix;
swfColorXform_t cxf;
const idMaterial * material;
int materialWidth;
int materialHeight;
int activeMasks;
uint8 blendMode;
float ratio;
stereoDepthType_t stereoDepth;
};
ID_INLINE swfRect_t::swfRect_t() :
tl( 0.0f, 0.0f ),
br( 0.0f, 0.0f )
{
}
ID_INLINE swfMatrix_t::swfMatrix_t() :
xx( 1.0f ), yy( 1.0f ),
yx( 0.0f ), xy( 0.0f ),
tx( 0.0f ), ty( 0.0f )
{
}
ID_INLINE idVec2 swfMatrix_t::Scale( const idVec2 & in ) const {
return idVec2( ( in.x * xx ) + ( in.y * xy ),
( in.y * yy ) + ( in.x * yx ) );
}
ID_INLINE idVec2 swfMatrix_t::Transform( const idVec2 & in ) const {
return idVec2( ( in.x * xx ) + ( in.y * xy ) + tx,
( in.y * yy ) + ( in.x * yx ) + ty );
}
ID_INLINE swfMatrix_t swfMatrix_t::Inverse() const {
swfMatrix_t inverse;
float det = ( ( xx * yy ) - ( yx * xy ) );
if ( idMath::Fabs( det ) < idMath::FLT_SMALLEST_NON_DENORMAL ) {
return *this;
}
float invDet = 1.0f / det;
inverse.xx = invDet * yy;
inverse.yx = invDet * -yx;
inverse.xy = invDet * -xy;
inverse.yy = invDet * xx;
//inverse.tx = invDet * ( xy * ty ) - ( yy * tx );
//inverse.ty = invDet * ( yx * tx ) - ( xx * ty );
return inverse;
}
ID_INLINE swfMatrix_t swfMatrix_t::Multiply( const swfMatrix_t & a ) const {
swfMatrix_t result;
result.xx = xx * a.xx + yx * a.xy;
result.yx = xx * a.yx + yx * a.yy;
result.xy = xy * a.xx + yy * a.xy;
result.yy = xy * a.yx + yy * a.yy;
result.tx = tx * a.xx + ty * a.xy + a.tx;
result.ty = tx * a.yx + ty * a.yy + a.ty;
return result;
}
ID_INLINE swfColorRGB_t::swfColorRGB_t() :
r( 255 ), g( 255 ), b( 255 )
{
}
ID_INLINE idVec4 swfColorRGB_t::ToVec4() const {
return idVec4( r * ( 1.0f / 255.0f ), g * ( 1.0f / 255.0f ), b * ( 1.0f / 255.0f ), 1.0f );
}
ID_INLINE swfColorRGBA_t::swfColorRGBA_t() :
a( 255 )
{
}
ID_INLINE idVec4 swfColorRGBA_t::ToVec4() const {
return idVec4( r * ( 1.0f / 255.0f ), g * ( 1.0f / 255.0f ), b * ( 1.0f / 255.0f ), a * ( 1.0f / 255.0f ) );
}
ID_INLINE swfLineStyle_t::swfLineStyle_t() :
startWidth( 20 ),
endWidth( 20 )
{
}
ID_INLINE swfGradientRecord_t::swfGradientRecord_t() :
startRatio( 0 ),
endRatio( 0 )
{
}
ID_INLINE swfGradient_t::swfGradient_t() :
numGradients( 0 )
{
}
ID_INLINE swfFillStyle_t::swfFillStyle_t() :
type( 0 ),
subType( 0 ),
focalPoint( 0.0f ),
bitmapID( 0 )
{
}
ID_INLINE swfColorXform_t::swfColorXform_t() :
mul( 1.0f, 1.0f, 1.0f, 1.0f ),
add( 0.0f, 0.0f, 0.0f, 0.0f )
{
}
ID_INLINE swfColorXform_t swfColorXform_t::Multiply( const swfColorXform_t & a ) const {
swfColorXform_t result;
result.mul = mul.Multiply( a.mul );
result.add = ( add.Multiply( a.mul ) ) + a.add;
return result;
}
ID_INLINE swfDisplayEntry_t::swfDisplayEntry_t() :
characterID( 0 ),
ratio( 0.0f ),
depth( 0 ),
clipDepth( 0 ),
blendMode( 0 ),
spriteInstance( NULL ),
textInstance( NULL )
{
}
ID_INLINE swfRenderState_t::swfRenderState_t() :
material( NULL ),
materialWidth( 0 ),
materialHeight( 0 ),
activeMasks( 0 ),
blendMode( 0 ),
ratio( 0.0f ),
stereoDepth( STEREO_DEPTH_TYPE_NONE )
{
}
ID_INLINE idSWFFontGlyph::idSWFFontGlyph() :
code( 0 ),
advance( 0 )
{
}
ID_INLINE idSWFFont::idSWFFont() :
fontID( 0 ),
ascent( 0 ),
descent( 0 ),
leading( 0 )
{
}
ID_INLINE idSWFTextRecord::idSWFTextRecord() :
fontID( 0 ),
xOffset( 0 ),
yOffset( 0 ),
textHeight( 0 ),
firstGlyph( 0 ),
numGlyphs( 0 )
{
}
ID_INLINE idSWFEditText::idSWFEditText() :
flags( SWF_ET_NONE ),
fontID( 0 ),
fontHeight( 24 ),
maxLength( 0xFFFF ),
align( SWF_ET_ALIGN_LEFT ),
leftMargin( 0 ),
rightMargin( 0 ),
indent( 0 ),
leading( 0 )
{
}
ID_INLINE swfGlyphEntry_t::swfGlyphEntry_t() :
index( 0 ),
advance( 0 )
{
}
#endif // !__SWF_TYPES1_H__

59
neo/swf/SWF_Zlib.cpp Normal file
View File

@@ -0,0 +1,59 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "../framework/zlib/zlib.h"
/*
========================
idSWF::Inflate
========================
*/
bool idSWF::Inflate( const byte * input, int inputSize, byte * output, int outputSize ) {
struct local_swf_alloc_t {
static void * zalloc( void * opaque, uint32 items, uint32 size ) {
return Mem_Alloc( items * size, TAG_SWF );
}
static void zfree( void * opaque, void * ptr ) {
Mem_Free( ptr );
}
};
z_stream stream;
memset( &stream, 0, sizeof( stream ) );
stream.next_in = (Bytef *)input;
stream.avail_in = inputSize;
stream.next_out = (Bytef *)output;
stream.avail_out = outputSize;
stream.zalloc = local_swf_alloc_t::zalloc;
stream.zfree = local_swf_alloc_t::zfree;
inflateInit( &stream );
bool success = ( inflate( &stream, Z_FINISH ) == Z_STREAM_END );
inflateEnd( &stream );
return success;
}