// programmer : ANDY
// website    : http://tw.myblog.yahoo.com/mmogc3d-mmogc3d/
// last date  : 2009.06.03

 

#include "AV_AniScript.h"

#include "AV_MemoryPool.h"

#include "AV_Other.h"

#include "AV_Utility.h"

#include "AV_IndexTable.hpp"

#include "AV_Encode.hpp"

#include "AV_CSDebug.h"

#include <wchar.h>

 

AniScriptEventInterface *gInterfaceLink;

 

//=============================================================================================================================================================

struct InfoNode

{

    WCHAR *Str;

    long   Value;

};

 

static InfoNode gAntiErrorNode = { L"NO", 0 };

 

struct ColumnInfo : AV_MemoryPoolStruct< InfoNode >

{

    inline InfoNode* Get( DWORD index )

    {

        if( index < ObjectMax )

            return &pBuffer[ index ];

        return &gAntiErrorNode; // here returns a parameter of non-NULL;

    }

};

 

//=============================================================================================================================================================

WCHAR *gAniCommandTable[ ANI_COMMAND_MAX ] =

{

    L"NULL",

 

    L"CREATE_ANI",

    L"CREATE_RECT",

    L"CTRL_ANI_START",

    L"CTRL_ANI_END",

    L"SET_ANI_RANGE",

    L"PLAY_ANI_RANGE",

    L"PLAY_ANI",

    L"CONTINUE_PLAY_ANI",

    L"WAIT_ANI",

    L"WAIT_ALL_ANI",

    L"WAIT",

    L"BREAK",

    L"PLAY_SOUND",

    L"SET_ANI",

    L"SET_IMAGE",

    L"SET_POS",

    L"SET_DELAY",

    L"SET_COLOR",

    L"SET_R",

    L"SET_G",

    L"SET_B",

    L"SET_A",

    L"SET_PIC_INDEX",

    L"SET_COUNT",

    L"SET_LAYER",

    L"SHOW_PIC",

    L"ADD_X",

    L"ADD_Y",

    L"FADE_IN",

    L"FADE_OUT",

    L"CALL_FUNC",

    L"CALL_SCRIPT",

    L"END_ANI",

    L"END",

};

DWORD gAniCommandValueTable[ ANI_COMMAND_MAX ];

 

struct AniNode

{

    DWORD     Number;

    DWORD     ImageIndex;

    DWORD     PicIndex, PicMax, BackupPicIndex;

    long      X, Y;

    BYTE      R, G, B;

    long      A, AMax, Aadd;

    DWORD     WaitFrameCount;

    DWORD     WaitFrameMax;

    long      RunCount;

    BOOL      PlayFlag;

    BOOL      PlayEndFlag;

 

    BOOL      UseRectFlag;

    POINT     RectSize;

 

    BOOL      InsertCommandFlag;

    AV_MemoryPoolPointerArray< ColumnInfo > InsertCommandTable;

};

 

#define ANI_UNLIMITED_COUNT  (-1)

 

#define ANI_LAYER_MAX   4

#define ANI_NODE_MAX    32

 

struct AniNodeManager : AV_MemoryPool2HeadArrayList< AniNode, ANI_NODE_MAX >

{

    DWORD Number;

};

 

#define COMMAND_INDEX_MAX   100

#define PARAMETER_MAX       10

struct AniLayerManager

{

    //------------------------------------------------------------

    AV_MemoryPool2HeadArrayList< AniNodeManager, ANI_LAYER_MAX > LayerTable;

    static IndexTableClass                                       sIndexCommandTable;

    AV_MemoryPoolArrayStruct< long, PARAMETER_MAX >              ParameterTable;

    AniNode           *pActNodeLink;

    AniNodeManager    *pActLayerLink;

    DWORD              RunCommandYIndex;

    long               WaitFrameCount;

    BOOL               PlayEndFlag;

    //------------------------------------------------------------

    void Create()

    {

        Reset();

 

        DWORD i = 0;

 

        LayerTable.Create();

        for( i = 0; i < ANI_LAYER_MAX; ++i )

        {

            AniNodeManager *manager = LayerTable.GetNode();

            manager->Create();

            manager->Number = i;

            LayerTable.Link( manager );

        }

 

        if( !sIndexCommandTable.IndexTable.pBuffer )

        {

            sIndexCommandTable.Create( COMMAND_INDEX_MAX, 100 );

            for( i = 1; i < ANI_COMMAND_MAX; ++i )

            {

                gAniCommandValueTable[ i ] = i;

                sIndexCommandTable.AddStrW( gAniCommandTable[ i ], &gAniCommandValueTable[ i ] );

            }

        }

 

        ParameterTable.Create();

    }

    void Release()

    {

        MPNode2< AniNode > *node = NULL, *del_node = NULL;

        MPNode2< AniNodeManager > *manager = LayerTable.pHeadNode;

 

        while( manager )

        {

            node = manager->pHeadNode;

            while( node )

            {

                del_node = node;

                node = node->pNext;

 

                del_node->InsertCommandTable.Clear();

                manager->Unlink( del_node );

                manager->ReleaseNode( del_node );

            }

            manager = manager->pNext;

        }

 

        Reset();

    }

    //------------------------------------------------------------

    void Reset()

    {

        pActNodeLink = NULL;

        pActLayerLink = NULL;

        RunCommandYIndex = 0;

        WaitFrameCount = 0;

        PlayEndFlag = FALSE;

    }

    //------------------------------------------------------------

    BOOL CheckCommandValue()

    {

        DWORD value_table[ ANI_COMMAND_MAX ] = { 0 };

        DWORD str_length = 0, add_value = 0, n = 0, i = 0;

        WCHAR *command = NULL;

        for( n = 1; n < ANI_COMMAND_MAX; ++n )

        {

            add_value = 0;

            str_length = (DWORD)wcslen( gAniCommandTable[ n ] );

            command = gAniCommandTable[ n ];

            for( i = 0; i < str_length; ++i )

            {

                add_value += command[ i ];

            }

            value_table[ n ] = add_value;

        }

 

        DWORD cmp_value = 0;

        for( n = 1; n < ANI_COMMAND_MAX; ++n )

        {

            cmp_value = value_table[ n ];

            for( i = n + 1; i < ANI_COMMAND_MAX; ++i )

            {

                if( cmp_value == value_table[ i ] )

                    return FALSE; // failed

            }

        }

 

        return TRUE;

    }

    //------------------------------------------------------------

    MPNode2< AniNode >* GetActNode( DWORD number )

    {

        MPNode2< AniNode > *mp_node = pActLayerLink->pHeadNode;

        while( mp_node )

        {

            if( mp_node->Number == number )

            {

                return mp_node;

            }

            mp_node = mp_node->pNext;

        }

        return NULL;

    }

    long GetValue( InfoNode *node )

    {

        if( node->Str[0] == L'P' )

        {

            DWORD length = (DWORD)wcslen( node->Str );

            WCHAR value_buff[ 4 ] = { 0 };

            if( length >= 4 )

                return node->Value; // for ignore the error.

 

            for( DWORD i = 1; i < length; ++i )

            {

                value_buff[ i - 1 ] = node->Str[ i ];

            }

            long *parameter_index = ParameterTable.Get( _wtoi( value_buff ) );

            if( parameter_index )

                return *parameter_index;

            return 0;

        }

        return node->Value;

    }

    //------------------------------------------------------------

    BOOL RunScript( struct ReadyPlayInfo *script );

    BOOL PlayAni( struct ReadyPlayInfo *script );

    //------------------------------------------------------------

};

IndexTableClass  AniLayerManager::sIndexCommandTable;

 

//#############################################################################################################################################################

//=============================================================================================================================================================

struct ScriptInfo

{

    DWORD                                    Number;

    AV_MemoryPoolCtrlStruct< DWORD >         CommandValueTable;

    AV_MemoryPoolPointerArray< ColumnInfo >  StringTable;

    BOOL                                     LoadFlag;

};

 

struct ReadyPlayInfo

{

    ScriptInfo *pScriptLink;

   

    DWORD                                    ManageNumber;

    AniLayerManager                          AniManager;

    BOOL                                     LoadFlag;

    BOOL                                     PlayFlag;

    class AniScriptManager                  *pParentLink;

 

    void Release()

    {

        PlayFlag = FALSE;

        AniManager.Release();

    }

};

 

#define LAYER_READY_NODE_MAX  100

struct ReadyScriptLayerNode : AV_MemoryPool2HeadArrayList< ReadyPlayInfo, LAYER_READY_NODE_MAX >

{

};

#define READY_SCRIPT_LAYER_MAX  3

 

class AniScriptManager : public AniScriptComponent

{

public :

    //------------------------------------------------------------

    DWORD                          TableCountYMax;

    AV_MemoryPoolStruct< WCHAR >   Buffer;

    DWORD                          BufferStartIndex;

    AV_MemoryPoolStruct< WCHAR >   TempSymbolBuffer;

    DWORD                          TempSymbolBufferUseIndex;

    DWORD                          StartYLineIndex;

    AV_MemoryPoolStruct< WCHAR* >  TempPointerBuffer;

    DWORD                          TempFileSize;

    //------------------------------------------------------------

    AV_MemoryPoolStruct< ScriptInfo >              ScriptTable;

    AV_MemoryPool2HeadList< ReadyScriptLayerNode > PlayScriptLayerList;

    //------------------------------------------------------------

    void                          *pUserInfo;

    BOOL                           AniDisplayFlag;

    //------------------------------------------------------------

    AniScriptManager( DWORD ani_script_max, DWORD table_y_max, DWORD temp_pointer_buffer_max, DWORD buffer_bytes_max );

    ~AniScriptManager();

    //------------------------------------------------------------

    ReadyScriptLayerNode* SearchReadyScriptLayerNode( DWORD layer_index );

    ReadyPlayInfo* SearchReadyPlayNode( DWORD layer_index, DWORD manage_number );

    void Run( ScriptInfo *script, DWORD column_y );

    //------------------------------------------------------------

public :

    //------------------------------------------------------------

    virtual void vRelease();

    //------------------------------------------------------------

    virtual BOOL vLoadScriptFile( WCHAR *path_file_name, DWORD script_index, BOOL decode_flag );

    //------------------------------------------------------------

    virtual BOOL vRunScript( DWORD script_index, DWORD manage_number, DWORD layer_index );

    virtual BOOL vPlayAni();

    virtual BOOL vPlayToEndScript( DWORD manage_number, DWORD layer_index );

    virtual BOOL vStopScript( DWORD manage_number, DWORD layer_index );

    virtual BOOL vSetParameter( DWORD manage_number, DWORD parameter_index, long parameter_value, DWORD layer_index );

    virtual BOOL vCheckScriptPlaying( DWORD manage_number, DWORD layer_index );

    virtual void vSetAniDisplayFlag( BOOL flag ){ AniDisplayFlag = flag; }

    //------------------------------------------------------------

};

 

//=============================================================================================================================================================

AniScriptComponent* AniScriptComponent::sCreate( AniScriptEventInterface *this_link, void *user_info, DWORD ani_script_max, DWORD table_y_max, DWORD temp_pointer_buffer_max, DWORD buffer_bytes_max )

{

    gInterfaceLink = this_link;

    AniScriptManager *obj = NULL;

    AVATAR_NEW( obj, AniScriptManager( ani_script_max, table_y_max, temp_pointer_buffer_max, buffer_bytes_max ) );

    obj->pUserInfo = user_info;

    return obj;

}

 

//=============================================================================================================================================================

void AniScriptManager::vRelease()

{

    AniScriptManager *_this = this;

    AVATAR_DELETE( _this );

}

 

//=============================================================================================================================================================

#define CHAR_BUFFER_MAX  2048

 

AniScriptManager::AniScriptManager( DWORD ani_script_max, DWORD table_y_max, DWORD temp_pointer_buffer_max, DWORD buffer_bytes_max )

{

    TableCountYMax = table_y_max;

 

    TempSymbolBuffer.Create( CHAR_BUFFER_MAX );

    TempPointerBuffer.Create( temp_pointer_buffer_max );

    Buffer.Create( buffer_bytes_max );

 

    BufferStartIndex = 0;

    TempSymbolBufferUseIndex = 0;

    StartYLineIndex = 0;

    TempFileSize = 0;

 

    ScriptInfo *script = NULL;

    ScriptTable.Create( ani_script_max );

 

    AniDisplayFlag = TRUE;

 

#if 0 // first check only.

    if( !ScriptTable.pBuffer[ 0 ].AniManager.CheckCommandValue() )

    {

        Debug::WBox( "AniScriptManager::AniScriptManager   error : some of values of ani command are equal." );

        ::Beep( 1000, 150 );

    }

#endif

 

    PlayScriptLayerList.Create( READY_SCRIPT_LAYER_MAX );

    for( DWORD i = 0; i < READY_SCRIPT_LAYER_MAX; ++i )

    {

        PlayScriptLayerList.Link( PlayScriptLayerList.GetNode() );

    }

    MPNode2< ReadyScriptLayerNode > *ready_layer_node = PlayScriptLayerList.pHeadNode;

    while( ready_layer_node )

    {

        ready_layer_node->Create();

        ready_layer_node = ready_layer_node->pNext;

    }

}

 

//=============================================================================================================================================================

AniScriptManager::~AniScriptManager()

{

    // just explain, I have release memories. (actually, they do not need to be released.)

    MPNode2< ReadyScriptLayerNode > *ready_layer_node = PlayScriptLayerList.pHeadNode;

    while( ready_layer_node )

    {

        PlayScriptLayerList.Unlink( ready_layer_node );

        PlayScriptLayerList.ReleaseNode( ready_layer_node );

    }

}

 

//=============================================================================================================================================================

ReadyScriptLayerNode* AniScriptManager::SearchReadyScriptLayerNode( DWORD layer_index )

{

    DWORD search_layer_index = 0;

    MPNode2< ReadyScriptLayerNode > *ready_layer_node = PlayScriptLayerList.pHeadNode;

    while( ready_layer_node )

    {

        if( search_layer_index == layer_index )

            return ready_layer_node;

        ++search_layer_index;

        ready_layer_node = ready_layer_node->pNext;

    }

    return NULL;

}

 

//=============================================================================================================================================================

ReadyPlayInfo* AniScriptManager::SearchReadyPlayNode( DWORD layer_index, DWORD manage_number )

{

    ReadyScriptLayerNode *ready_layer_node = SearchReadyScriptLayerNode( layer_index );

    if( !ready_layer_node )

        return NULL;

 

    MPNode2< ReadyPlayInfo > *ready_node = ready_layer_node->pHeadNode;

    while( ready_node )

    {

        if( ready_node->ManageNumber == manage_number )

            return ready_node;

        ready_node = ready_node->pNext;

    }

    return NULL;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vSetParameter( DWORD manage_number, DWORD parameter_index, long parameter_value, DWORD layer_index )

{

    ReadyPlayInfo *ready_node = SearchReadyPlayNode( layer_index, manage_number );

    if( !ready_node )

        return FALSE;

    long *parameter = ready_node->AniManager.ParameterTable.Get( parameter_index );

    if( !parameter )

        return FALSE;

    *parameter = parameter_value;

    return TRUE;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vCheckScriptPlaying( DWORD manage_number, DWORD layer_index )

{

    ReadyPlayInfo *ready_node = SearchReadyPlayNode( layer_index, manage_number );

    if( !ready_node )

        return FALSE;

    return ready_node->PlayFlag;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vRunScript( DWORD script_index, DWORD manage_number, DWORD layer_index )

{

    ScriptInfo *script = ScriptTable.Get( script_index );

    if( !script )

        return FALSE;

 

    ReadyScriptLayerNode *ready_layer_node = SearchReadyScriptLayerNode( layer_index );

    if( !ready_layer_node )

        return FALSE;

 

    ReadyPlayInfo *ready_node = SearchReadyPlayNode( layer_index, manage_number );

    if( ready_node )

    {

        ready_node->AniManager.Reset();

        if( ready_node->PlayFlag )

            return TRUE;

        return FALSE;

    }

 

    ready_node = ready_layer_node->GetNode();

    ready_node->ManageNumber = manage_number;

    ready_node->AniManager.Create();

    ready_node->pScriptLink = script;

    ready_node->PlayFlag = TRUE;

    ready_node->pParentLink = this;

    ready_layer_node->Link( ready_node );

    return TRUE;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vPlayToEndScript( DWORD manage_number, DWORD layer_index )

{

    ReadyPlayInfo *ready_node = SearchReadyPlayNode( layer_index, manage_number );

    if( !ready_node )

        return FALSE;

    if( !ready_node->PlayFlag )

        return FALSE;

    ready_node->AniManager.PlayEndFlag = TRUE;

    return TRUE;

 

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vStopScript( DWORD manage_number, DWORD layer_index )

{

    ReadyScriptLayerNode *ready_layer_node = SearchReadyScriptLayerNode( layer_index );

    if( !ready_layer_node )

        return FALSE;

 

    MPNode2< ReadyPlayInfo > *ready_node = ready_layer_node->pHeadNode, *del_node = NULL;

    while( ready_node )

    {

        if( ready_node->ManageNumber == manage_number )

        {

            gInterfaceLink->vOnScriptEnd( ready_node->pParentLink->pUserInfo,

                                            ready_node->pScriptLink->Number,

                                            ready_node->ManageNumber );

            ready_node->Release();

            del_node = ready_node;

            ready_layer_node->Unlink( del_node );

            ready_layer_node->ReleaseNode( del_node );

            break;

        }

        ready_node = ready_node->pNext;

    }

    return TRUE;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vPlayAni()

{

    BOOL script_run_flag = FALSE;

    MPNode2< ReadyPlayInfo > *ready_node = NULL, *del_node = NULL;

 

    MPNode2< ReadyScriptLayerNode > *ready_layer_node = PlayScriptLayerList.pHeadNode;

    while( ready_layer_node )

    {

        ready_node = ready_layer_node->pHeadNode, del_node = NULL;

        while( ready_node )

        {

            script_run_flag = ready_node->AniManager.RunScript( ready_node );

            ready_node->AniManager.PlayAni( ready_node );

            if( !script_run_flag )

            {

                gInterfaceLink->vOnScriptEnd(

                    ready_node->pParentLink->pUserInfo,

                    ready_node->ManageNumber, ready_node->pScriptLink->Number );

                ready_node->Release();

                del_node = ready_node;

                ready_node = ready_node->pNext;

                ready_layer_node->Unlink( del_node );

                ready_layer_node->ReleaseNode( del_node );

                continue;

            }

            ready_node = ready_node->pNext;

        }

        ready_layer_node = ready_layer_node->pNext;

    }

 

    return TRUE;

}

 

//=============================================================================================================================================================

BOOL AniScriptManager::vLoadScriptFile( WCHAR *path_file_name, DWORD script_index, BOOL decode_flag )

{

    ScriptInfo *script = ScriptTable.Get( script_index );

    if( !script )

        return FALSE;

 

    if( script->LoadFlag == TRUE )

        return TRUE;

 

    script->CommandValueTable.Create( TableCountYMax );

    script->StringTable.Create( TableCountYMax );

 

    DWORD file_size = 0;

    BOOL flag = FALSE;

    WCHAR encode_path_file_name[ 256 ];

 

    if( decode_flag )

    {

        file_size = Buffer.GetFileSize( path_file_name );

        if( file_size > Buffer.BufferSize )

        {

            Debug::WBox( "AniScriptManager::vLoadScriptFile   error : the size of buffer is not enough. (%s) if( file_size(%d) > Buffer.BufferSize(%d) )", path_file_name, file_size, Buffer.BufferSize );

            return FALSE;

        }

 

        flag = Buffer.Load( path_file_name );

        FILE_ENCODE_0( FILE_ENCODE_STATIC_CODE, Buffer.pBuffer, file_size );

    }

    else

    {

        size_t length = wcslen( path_file_name );

        wcscpy_s( encode_path_file_name, 256, path_file_name );

        if( encode_path_file_name[ length - 3 ] == 'e' &&

            encode_path_file_name[ length - 2 ] == 'n' &&

            encode_path_file_name[ length - 1 ] == 'c' )

            encode_path_file_name[ length - 4 ] = 0; // delete .enc

 

        file_size = Buffer.GetFileSize( encode_path_file_name );

        if( file_size > Buffer.BufferSize )

        {

            Debug::WBox( "AniScriptManager::vLoadScriptFile   error : the size of buffer is not enough. (%s) if( file_size(%d) > Buffer.BufferSize(%d) )", encode_path_file_name, file_size, Buffer.BufferSize );

            return FALSE;

        }

 

        flag = Buffer.Load( encode_path_file_name );

    }

 

    if( !flag )

        return flag;

 

    BufferStartIndex = 0;

    TempSymbolBufferUseIndex = 0;

    StartYLineIndex = 0;

    TempFileSize = file_size;

 

    WCHAR *p = &Buffer.pBuffer[ BufferStartIndex ];

    if( *p == 65279 ) // 65279 is a first symbol for unicode file.

    {

        ++BufferStartIndex;

        ++p;

    }

    Run( script, 99999999 );

 

    script->Number = script_index;

    script->LoadFlag = TRUE;

 

    return flag;

}

 

//=============================================================================================================================================================

void AniScriptManager::Run( ScriptInfo *script, DWORD column_y )

{

    WCHAR *p = &Buffer.pBuffer[ BufferStartIndex ];

    DWORD count = BufferStartIndex;

    const DWORD buff_max = TempFileSize / 2;

    WCHAR c = 0;

    DWORD column_x = 0;

    ColumnInfo *column = NULL;

    DWORD i = 0;

    DWORD str_length = 0, add_value = 0;

 

    const static WCHAR end1_key     = '\r'; // 13

    const static WCHAR end2_key     = '\n'; // 10

    const static WCHAR space_key    = 32;

    const static WCHAR tab_key      = 9;

    const static WCHAR explain_key  = ';';

    const static WCHAR separate_key = ',';

 

    while( 1 )

    {

        // first get symbol

        while( 1 )

        {

            if( count++ >= buff_max )

            {

                BufferStartIndex = buff_max;

                return;

            }

 

            c = *p++;

 

            if( c == space_key || c == tab_key )

            {

            }

            else if( c == explain_key )

            {

                BOOL break_flag = FALSE;

                while( 1 )

                {

                    if( count++ >= buff_max )

                    {

                        break_flag = TRUE;

                        break;

                    }

                    c = *p++;

 

                    if( c == end1_key )

                    {

                        if( count++ >= buff_max )

                        {

                            break_flag = TRUE;

                            break;

                        }

                        c = *p++;

                        if( c == end2_key )

                            break; // break this line

                    }

                }

                if( break_flag )

                    break;

                continue;

            }

            else if( c == end1_key )

            {

                if( count++ >= buff_max )

                    break;

                c = *p++; // end2_key

            }

            else

            {

                TempSymbolBuffer.pBuffer[ TempSymbolBufferUseIndex++ ] = c;

                break;

            }

        }

 

        //----------------------------------------------------

 

        // get column text

        while( 1 )

        {

            if( count++ >= buff_max ) // to end...

                break;

 

            c = *p++;

 

            if( c == space_key || c == tab_key || c == separate_key || c == end1_key || count == buff_max )

            {

                if( TempSymbolBufferUseIndex == 0 )

                    continue;

 

                if( count == buff_max )

                {

                    TempSymbolBuffer.pBuffer[ TempSymbolBufferUseIndex ] = c;

                    ++TempSymbolBufferUseIndex;

                }

 

                TempSymbolBuffer.pBuffer[ TempSymbolBufferUseIndex ] = 0;

               

                //---------------------

                WCHAR *str = (WCHAR*)AV_KernelMemoryPool::sMemoryAllocate( (TempSymbolBufferUseIndex + 1) * sizeof(WCHAR) );

                wmemcpy( str, TempSymbolBuffer.pBuffer, TempSymbolBufferUseIndex );

                str[ TempSymbolBufferUseIndex ] = 0;

                //---------------------

 

                if( column_x < TempPointerBuffer.ObjectMax )

                    TempPointerBuffer.pBuffer[ column_x ] = str;

                else

                {

                    Debug::WBox( L"AniScriptManager::Run   error : StartYLineIndex= %d, parameter_count(%d) > pointer_buffer_count(%d), newstr= %s", StartYLineIndex, column_x, TempPointerBuffer.ObjectMax, str );

                }

 

                TempSymbolBufferUseIndex = 0;

                ++column_x;

 

                //-------------------------------------------

 

                if( count == buff_max )

                    break;

 

                if( c == end1_key )

                {

                    if( count++ >= buff_max )

                        break;

                    c = *p++;

                    if( c == end2_key )

                        break; // break this line

                }

            }

            else if( c == explain_key )

            {

                // here jumps those symbols of junk, like explain.

                while( 1 )

                {

                    if( count++ >= buff_max ) // to end...

                        break;

                    c = *p++;

 

                    if( c != end1_key )

                    {

                    }

                    else

                    {

                        if( count++ >= buff_max ) // to end...

                            break;

                        c = *p++;

                        if( c == end2_key )

                            break; // break this line

                    }

                }

                break;

            }

            else

            {

                TempSymbolBuffer.pBuffer[ TempSymbolBufferUseIndex ] = c;

                ++TempSymbolBufferUseIndex;

            }

        }

 

        if( script->StringTable.UseCount < TableCountYMax )

        {

            ++script->StringTable.UseCount;

            column = (ColumnInfo*)AV_KernelMemoryPool::sMemoryAllocate( sizeof( ColumnInfo ) );

            script->StringTable.pBuffer[ StartYLineIndex ] = column;

            column->Create( column_x );

 

            for( i = 0; i < column_x; i++ )

            {

                column->pBuffer[ i ].Str   = TempPointerBuffer.pBuffer[ i ];

                column->pBuffer[ i ].Value = _wtoi( TempPointerBuffer.pBuffer[ i ] );

            }

 

            //---------

 

            add_value = 0;

            str_length = (DWORD)wcslen( column->pBuffer[ 0 ].Str );

            for( i = 0; i < str_length; i++ )

            {

                add_value += column->pBuffer[ 0 ].Str[ i ];

            }

            script->CommandValueTable.pBuffer[ script->StringTable.UseCount - 1 ] = add_value;

        }

        else

        {

            Debug::WBox( L"AniScriptManager::Run   error : script->StringTable.UseCount(%d) >= TableCountYMax(%d)", script->StringTable.UseCount, TableCountYMax );

            return;

        }

 

        if( column_y == StartYLineIndex )

        {

            BufferStartIndex = count;

            ++StartYLineIndex;

            return;

        }

 

        column_x = 0;

        ++StartYLineIndex;

    }

 

}

 

//#############################################################################################################################################################

//=============================================================================================================================================================

BOOL AniLayerManager::PlayAni( ReadyPlayInfo *ready_node )

{

    MPNode2< AniNode > *node = NULL, *del_node = NULL;

    MPNode2< AniNodeManager > *manager = LayerTable.pHeadNode;

 

    while( manager )

    {

        node = manager->pHeadNode;

        while( node )

        {

            if( !node->PlayFlag )

            {

                node = node->pNext;

                continue;

            }

 

            if( ready_node->pParentLink->AniDisplayFlag )

            {

                if( node->UseRectFlag )

                {

                    RECT rect;

                    rect.left   = node->X;

                    rect.top    = node->Y;

                    rect.right  = rect.left + node->RectSize.x;

                    rect.bottom = rect.top  + node->RectSize.y;

                    gInterfaceLink->vOnScriptColorRect(

                                            &rect,

                                            node->R,

                                            node->G,

                                            node->B,

                                            (BYTE)node->A );

                }

                else

                {

                    gInterfaceLink->vOnScriptAniUpdate( ready_node->pParentLink->pUserInfo,

                                                ready_node->pScriptLink->Number,

                                                ready_node->ManageNumber,

                                                node->Number,

                                                node->PicIndex );

 

                    gInterfaceLink->vOnScriptDraw( node->ImageIndex,

                                            node->X,

                                            node->Y,

                                            node->PicIndex,

                                            NULL,

                                            A_RENDER_STATE__COLOR_KEY,

                                            node->R,

                                            node->G,

                                            node->B,

                                            (BYTE)node->A );

                }

 

                if( node->Aadd )

                    node->A = (node->A += node->Aadd) > node->AMax ? node->AMax : node->A;

            }

 

            if( !node->PlayEndFlag &&

                ++node->WaitFrameCount >= node->WaitFrameMax + ClockInfo::sGetANIWhileFrames() )

            {

                node->WaitFrameCount = 0;

                if( ++node->PicIndex > node->PicMax )

                {

                    --node->PicIndex;

                }

            }

 

//          if( node->InsertCommandFlag ) // retain

//          {

//          }

 

            node = node->pNext;

        }

        manager = manager->pNext;

    }

 

    if( LayerTable.LinkNodeCount == 0 )

        return FALSE;

    return TRUE;

}

 

//=============================================================================================================================================================

BOOL AniLayerManager::RunScript( ReadyPlayInfo *ready_node )

{

    DWORD command = 0, command_max = ready_node->pScriptLink->StringTable.UseCount;

    ITNode *index_node =NULL;

    AniNode *node = NULL;

    MPNode2< AniNode > *act_node = NULL;

    AniNodeManager *manager = (AniNodeManager*)LayerTable.pHeadNode;

    ColumnInfo *column = NULL;

 

    pActLayerLink = manager;

 

    for( ; RunCommandYIndex < command_max; RunCommandYIndex++ )

    {

        column = ready_node->pScriptLink->StringTable.pBuffer[ RunCommandYIndex ];

        index_node = sIndexCommandTable.SearchValueByValue( ready_node->pScriptLink->CommandValueTable.pBuffer[ RunCommandYIndex ] );

        if( !index_node )

            continue; // failed

        command = *((DWORD*)index_node->pDataLink);

        switch( command )

        {

        case ANI_COMMAND__CREATE_ANI :

            {

                pActNodeLink = node = pActLayerLink->GetNode();

                pActLayerLink->Link( node );

                node->Number          = GetValue( column->Get( 1 ) );

                node->ImageIndex      = GetValue( column->Get( 2 ) );

                node->X               = GetValue( column->Get( 3 ) );

                node->Y               = GetValue( column->Get( 4 ) );

                node->WaitFrameMax    = GetValue( column->Get( 5 ) );

                node->R               = 255;

                node->G               = 255;

                node->B               = 255;

                node->A               = 255;

                node->Aadd            = GetValue( column->Get( 6 ) );

                node->AMax            = 255;

                node->RunCount        = 1;

 

                if( node->Aadd )

                    node->A = 0;

                break;

            }

        case ANI_COMMAND__CREATE_RECT :

            {

                pActNodeLink = node = pActLayerLink->GetNode();

                pActLayerLink->Link( node );

                node->Number          = GetValue( column->Get( 1 ) );

                node->X               = GetValue( column->Get( 2 ) );

                node->Y               = GetValue( column->Get( 3 ) );

                node->RectSize.x      = GetValue( column->Get( 4 ) );

                node->RectSize.y      = GetValue( column->Get( 5 ) );

                node->R               = (BYTE)GetValue( column->Get( 6 ) );

                node->G               = (BYTE)GetValue( column->Get( 7 ) );

                node->B               = (BYTE)GetValue( column->Get( 8 ) );

                node->A = node->AMax  = GetValue( column->Get( 9 ) );

                node->Aadd            = GetValue( column->Get( 10 ) );

                node->UseRectFlag     = TRUE;

                node->RunCount        = 1;

                node->PlayFlag = TRUE;

 

                if( node->Aadd )

                    node->A = 0;

                break;

            }

        case ANI_COMMAND__CTRL_ANI_START :

            {

                break;

            }

        case ANI_COMMAND__CTRL_ANI_END :

            {

                break;

            }

        case ANI_COMMAND__SET_ANI_RANGE :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

                act_node->PicIndex = GetValue( column->Get( 2 ) );

                act_node->PicMax   = GetValue( column->Get( 3 ) );

                act_node->PlayFlag = TRUE;

                act_node->BackupPicIndex = act_node->PicIndex;

 

                break;

            }

        case ANI_COMMAND__PLAY_ANI_RANGE :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

                act_node->PicIndex = GetValue( column->Get( 2 ) );

                act_node->PicMax   = GetValue( column->Get( 3 ) );

                act_node->PlayFlag = TRUE;

                act_node->BackupPicIndex = act_node->PicIndex;

 

                ++RunCommandYIndex; // to play

                return TRUE;

            }

        case ANI_COMMAND__PLAY_ANI :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

                act_node->PicIndex = 0;

                act_node->PicMax   = gInterfaceLink->vOnScriptGetImageCount( node->ImageIndex );

                act_node->PlayFlag = TRUE;

                act_node->BackupPicIndex = act_node->PicIndex;

 

                ++RunCommandYIndex; // to play

                return TRUE;

            }

        case ANI_COMMAND__CONTINUE_PLAY_ANI :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

//              act_node->PicIndex = 0; // no clear, continue to use same PicIndex.

                act_node->PicMax   = gInterfaceLink->vOnScriptGetImageCount( node->ImageIndex );

                act_node->PlayFlag = TRUE;

                act_node->BackupPicIndex = act_node->PicIndex;

 

                ++RunCommandYIndex; // to play

                return TRUE;

            }

        case ANI_COMMAND__WAIT_ANI :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

                if( PlayEndFlag )

                    break;

                if( act_node->PicIndex >= act_node->PicMax )

                {

                    if( act_node->RunCount <= ANI_UNLIMITED_COUNT ||

                        --act_node->RunCount > 0 )

                    {

                        act_node->PicIndex = act_node->BackupPicIndex;

                    }

                    else

                        break;

                }

                return TRUE;

            }

        case ANI_COMMAND__WAIT_ALL_ANI :

            {

                DWORD end_count = 0;

                act_node = pActLayerLink->pHeadNode;

                while( act_node )

                {

                    if( !act_node->PlayFlag || act_node->PlayEndFlag )

                    {

                        act_node = act_node->pNext;

                        ++end_count;

                        continue;

                    }

 

                    if( act_node->PicIndex >= act_node->PicMax )

                    {

                        if( act_node->RunCount <= ANI_UNLIMITED_COUNT )

                        {

                            act_node->PicIndex = act_node->BackupPicIndex;

                        }

                        else

                        {

                            if( --act_node->RunCount > 0 )

                            {

                                act_node->PicIndex = act_node->BackupPicIndex;

                            }

                            else

                            {

                                if( act_node->PicMax > 0 )

                                    act_node->PicIndex = act_node->PicMax - 1;

                                else

                                    act_node->PicIndex = 0;

                                act_node->PlayEndFlag = TRUE;

                                ++end_count;

                            }

                        }

                    }

                    act_node = act_node->pNext;

                }

                if( end_count == pActLayerLink->LinkNodeCount )

                    break;

                return TRUE;

            }

        case ANI_COMMAND__WAIT :

            {

                if( PlayEndFlag )

                    break;

                if( ++WaitFrameCount >= GetValue( column->Get( 1 ) ) + ClockInfo::sGetANIWhileFrames() )

                {

                    WaitFrameCount = 0;

                    break;

                }

                return TRUE;

            }

        case ANI_COMMAND__BREAK :

            {

                ++RunCommandYIndex;

                return TRUE;

            }

        case ANI_COMMAND__PLAY_SOUND :

            {

                gInterfaceLink->vOnScriptPlaySound( ready_node->pParentLink->pUserInfo,

                    GetValue( column->Get( 1 ) ) );

                break;

            }

        case ANI_COMMAND__SET_ANI :

            {

                pActNodeLink = GetActNode( GetValue( column->Get( 1 ) ) );

                break;

            }

        case ANI_COMMAND__SET_IMAGE :

            {

                if( pActNodeLink )

                    pActNodeLink->ImageIndex = GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_POS :

            {

                if( pActNodeLink )

                {

                    pActNodeLink->X = GetValue( column->Get( 1 ) );

                    pActNodeLink->Y = GetValue( column->Get( 2 ) );

                }

                break;

            }

        case ANI_COMMAND__SET_DELAY :

            {

                if( pActNodeLink )

                    pActNodeLink->WaitFrameMax = GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_COLOR :

            {

                if( pActNodeLink )

                {

                    pActNodeLink->R = (BYTE)GetValue( column->Get( 1 ) );

                    pActNodeLink->G = (BYTE)GetValue( column->Get( 2 ) );

                    pActNodeLink->B = (BYTE)GetValue( column->Get( 3 ) );

                    pActNodeLink->A = (BYTE)GetValue( column->Get( 4 ) );

                }

                break;

            }

        case ANI_COMMAND__SET_R :

            {

                if( pActNodeLink )

                    pActNodeLink->R = (BYTE)GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_G :

            {

                if( pActNodeLink )

                    pActNodeLink->G = (BYTE)GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_B :

            {

                if( pActNodeLink )

                    pActNodeLink->B = (BYTE)GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_A :

            {

                if( pActNodeLink )

                {

                    pActNodeLink->A    = (BYTE)GetValue( column->Get( 1 ) );

                    pActNodeLink->Aadd = (BYTE)GetValue( column->Get( 2 ) );

                    InfoNode *node = column->Get( 3 );

                    if( ::wcscmp( node->Str, gAntiErrorNode.Str ) != 0 )

                        pActNodeLink->AMax = (BYTE)GetValue( column->Get( 3 ) );

                }

                break;

            }

        case ANI_COMMAND__SET_PIC_INDEX :

            {

                if( pActNodeLink )

                    pActNodeLink->PicIndex = (BYTE)GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_COUNT :

            {

                if( pActNodeLink )

                    pActNodeLink->RunCount = GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__SET_LAYER :

            {

                break;

            }

        case ANI_COMMAND__SHOW_PIC :

            {

                if( pActNodeLink )

                {

                    pActNodeLink->PicIndex = GetValue( column->Get( 1 ) );

                    pActNodeLink->BackupPicIndex = pActNodeLink->PicIndex;

                    pActNodeLink->PlayFlag = TRUE;

                }

                break;

            }

        case ANI_COMMAND__ADD_X :

            {

                if( pActNodeLink )

                    pActNodeLink->X += GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__ADD_Y :

            {

                if( pActNodeLink )

                    pActNodeLink->Y += GetValue( column->Get( 1 ) );

                break;

            }

        case ANI_COMMAND__FADE_IN :

            {

                DWORD alpha_sub = GetValue( column->Get( 1 ) );

                act_node = pActLayerLink->pHeadNode;

                BOOL fade_in_running_flag = FALSE;

                while( act_node )

                {

                    if( act_node->A < act_node->AMax )

                    {

                        act_node->A += alpha_sub;

                        if( act_node->A > act_node->AMax )

                            act_node->A = act_node->AMax;

                        fade_in_running_flag = TRUE;

                    }

                    act_node = act_node->pNext;

                }

                if( fade_in_running_flag )

                    return TRUE;

                break;

            }

        case ANI_COMMAND__FADE_OUT :

            {

                DWORD alpha_sub = GetValue( column->Get( 1 ) );

                act_node = pActLayerLink->pHeadNode;

                BOOL fade_out_running_flag = FALSE;

                act_node->Aadd = 0;

                while( act_node )

                {

                    if( act_node->A > 0 )

                    {

                        act_node->A -= alpha_sub;

                        if( act_node->A < 0 )

                            act_node->A = 0;

                        fade_out_running_flag = TRUE;

                    }

                    act_node = act_node->pNext;

                }

                if( fade_out_running_flag )

                    return TRUE;

                break;

            }

        case ANI_COMMAND__CALL_FUNC :

            {

                gInterfaceLink->vOnScriptExtraFunc( ready_node->pParentLink->pUserInfo,

                    ready_node->pScriptLink->Number,

                    ready_node->ManageNumber, GetValue( column->Get( 1 ) ) );

                break;

            }

        case ANI_COMMAND__CALL_SCRIPT :

            {

                break;

            }

        case ANI_COMMAND__END_ANI :

            {

                if( !(act_node = GetActNode( GetValue( column->Get( 1 ) ) )) )

                    break;

                gInterfaceLink->vOnScriptAniEnd( ready_node->pParentLink->pUserInfo,

                    ready_node->pScriptLink->Number,

                    ready_node->ManageNumber, act_node->Number );

 

                pActLayerLink->Unlink( act_node );

                pActLayerLink->ReleaseNode( act_node );

                break;

            }

        case ANI_COMMAND__END :

            {

                return FALSE;

            }

        }

    }

 

    return FALSE; // end script

}

 

// eof