mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2026-03-20 00:49:47 +01:00
Initial commit
This commit is contained in:
405
neo/swf/SWF.h
Normal file
405
neo/swf/SWF.h
Normal 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
402
neo/swf/SWF_Bitstream.cpp
Normal 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
145
neo/swf/SWF_Bitstream.h
Normal 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
155
neo/swf/SWF_Dictionary.cpp
Normal 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
222
neo/swf/SWF_Enums.h
Normal 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
457
neo/swf/SWF_Events.cpp
Normal 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
575
neo/swf/SWF_Image.cpp
Normal 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
458
neo/swf/SWF_Load.cpp
Normal 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
709
neo/swf/SWF_Main.cpp
Normal 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
215
neo/swf/SWF_Names.cpp
Normal 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
85
neo/swf/SWF_ParmList.cpp
Normal 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
60
neo/swf/SWF_ParmList.h
Normal 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
231
neo/swf/SWF_PlaceObject.cpp
Normal 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
1536
neo/swf/SWF_Render.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1255
neo/swf/SWF_ScriptFunction.cpp
Normal file
1255
neo/swf/SWF_ScriptFunction.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
neo/swf/SWF_ScriptFunction.h
Normal file
184
neo/swf/SWF_ScriptFunction.h
Normal 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__
|
||||
580
neo/swf/SWF_ScriptObject.cpp
Normal file
580
neo/swf/SWF_ScriptObject.cpp
Normal 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
189
neo/swf/SWF_ScriptObject.h
Normal 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
422
neo/swf/SWF_ScriptVar.cpp
Normal 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
148
neo/swf/SWF_ScriptVar.h
Normal 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
903
neo/swf/SWF_ShapeParser.cpp
Normal 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
89
neo/swf/SWF_ShapeParser.h
Normal 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
110
neo/swf/SWF_Shapes.cpp
Normal 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
45
neo/swf/SWF_Sounds.cpp
Normal 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 ) {
|
||||
}
|
||||
1363
neo/swf/SWF_SpriteInstance.cpp
Normal file
1363
neo/swf/SWF_SpriteInstance.cpp
Normal file
File diff suppressed because it is too large
Load Diff
258
neo/swf/SWF_SpriteInstance.h
Normal file
258
neo/swf/SWF_SpriteInstance.h
Normal 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
257
neo/swf/SWF_Sprites.cpp
Normal 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
81
neo/swf/SWF_Sprites.h
Normal 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
306
neo/swf/SWF_Text.cpp
Normal 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
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
251
neo/swf/SWF_TextInstance.h
Normal 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
410
neo/swf/SWF_Types.h
Normal 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
59
neo/swf/SWF_Zlib.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user