Subversion Repositories spk

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

// LcdCustomScreen.cpp: implementation of the CLcdCustomScreen class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "LcdCustomScreen.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CLcdCustomScreen::CLcdCustomScreen( CEzLcd *lcd )
{
        m_pLcd = lcd;
        m_iArraySize = 10;
        m_pHandles = (HANDLE *)malloc(sizeof(HANDLE) * m_iArraySize);
        m_iCycles = 10;
        m_bDebug = false;
        m_pMoveObject = m_pEndMoveObject = NULL;
        m_pText = m_pEndText = NULL;
}

CLcdCustomScreen::~CLcdCustomScreen()
{
        Reset ();
        free ( m_pHandles );
}

void CLcdCustomScreen::IncreaseArraySize ()
{
        m_iArraySize += 5;
        m_pHandles = (HANDLE *)realloc(m_pHandles, sizeof(HANDLE) * m_iArraySize);
}

CyString CLcdCustomScreen::ParseFilename(CyString &filename, CyString &dir)
{
        CyString f = filename;
        
        f = f.FindReplace("$progdir", m_sProgDir);
        f = f.FindReplace("$gamedir", m_sGameDir);

        // relative filename
        if ( !f.IsIn(":") )
                f = dir + "/" + f;

        f = f.FindReplace("/", "\\");
        f = f.FindReplace("\\\\", "\\");
        return f;
}
bool CLcdCustomScreen::LoadScript ( CyString sDir, CyString sProgDir, const char *filename )
{
        m_lDebugLog.Clear();
        m_lVaribles.Clear();

        int iCurrentPos = 0;

        m_iStartPage = m_pLcd->AddNewPage () - 1;
    m_pLcd->ModifyControlsOnPage( m_iStartPage );

        int iLastX, iLastY;

        m_bDebug = false;
        CyString fname = filename;
        fname = fname.FindReplace("$progdir", sProgDir);

        // relative path
        if ( !fname.IsIn(":") )
                fname = sDir + "/" + filename;
        fname = fname.FindReplace("\\", "/"); // make sure we're using the correct slash
        fname = fname.FindReplace("//", "/"); // remove any double slashes
        CyString dir = fname.GetToken("/", 1, -1);

        m_sScriptDir = dir;
        m_sProgDir = sProgDir;
        m_sGameDir = sDir;

        FILE *id = fopen ( fname.c_str(), "r" );
        if ( id )
        {
                int iLine = 0;
                while ( !feof(id) )
                {
                        CyString line;
                        line = line.GetEndOfLine ( id, &iLine, false );
                        if ( (line.Left (2) == "//") || (line.Empty()) )
                                continue;
                        CyString arg = line.GetToken ( 1, ' ' ).ToLower();
                        if ( arg == "displayfor:" )
                        {
                                m_iCycles = line.GetToken ( 2, ' ' ).ToInt();
                                if ( (!m_iCycles) || (m_iCycles < 0) )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + (CyString(": Invalid argument for \"DisplayFor\" (") + line.GetToken ( 2, ' ' )) + ")", false );
                        }
                        else if ( arg == "debug" )
                                m_bDebug = true;
                        else if ( arg == "varible:" )
                        {
                                if ( line.NumToken ( ' ' ) < 2 )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Missing Argument for \"Varible\""), false );
                                else
                                        m_lVaribles.PushBack ( line.GetToken ( 2, ' ' ) );
                        }
                        else if ( arg == "icon:" )
                        {
                                if ( line.NumToken ( ' ' ) < 6 )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Missing Arguments for \"Icon\""), false );
                                else
                                {
                                        CyString sIcon = line.GetToken ( 6, -1, ' ' );
                                        int iSizeX = line.GetToken ( 4, ' ' ).ToInt();
                                        int iSizeY = line.GetToken ( 5, ' ' ).ToInt();
                                        HICON hIcon = static_cast<HICON>(LoadImage(0, (LPCTSTR)ParseFilename(sIcon, dir).c_str(), IMAGE_ICON, iSizeX, iSizeY, LR_LOADFROMFILE));
                                        if ( FAILED (hIcon) )
                                                m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Unable to open icon file: ") + sIcon, false );
                                        else
                                        {
                                                m_pHandles[iCurrentPos] = m_pLcd->AddIcon(hIcon, iSizeX, iSizeY);
                                                int iX = line.GetToken ( 2, ' ' ).ToInt ();
                                                int iY = line.GetToken ( 3, ' ' ).ToInt ();
                                                m_pLcd->SetOrigin ( m_pHandles[iCurrentPos], iX, iY );
                                                iLastX = iX;
                                                iLastY = iY;
                                                iCurrentPos++;
                                        }
                                }
                        }
                        else if ( (arg == "move:") || (arg == "moverepeat:") )
                        {
                                if ( line.NumToken ( ' ' ) < 4 )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Missing Argument for \"Move\""), false );
                                else if ( !iCurrentPos )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": No object before move command"), false );
                                else
                                {
                                        SMoveObject *o = new SMoveObject;
                                        o->hObject = m_pHandles[iCurrentPos - 1];
                                        if ( arg == "moverepeat:" )
                                                o->bRepeat = true;
                                        else
                                                o->bRepeat = false;
                                        o->iStartX = iLastX;
                                        o->iStartY = iLastY;
                                        if ( line.GetToken ( 2, ' ' ) == "-" )
                                                o->iEndX = o->iStartX;
                                        else
                                                o->iEndX = line.GetToken ( 2, ' ' ).ToInt();
                                        if ( line.GetToken ( 3, ' ' ) == "-" )
                                                o->iEndY = o->iStartY;
                                        else
                                                o->iEndY = line.GetToken ( 3, ' ' ).ToInt();
                                        o->iTimeRemaining = o->iTotalTime = line.GetToken ( 4, ' ' ).ToInt();
                                        AddMoveObject ( o );
                                }
                        }
                        else if ( ((arg.Left(9) == "textsmall") || (arg.Left(10) == "textmedium") || (arg.Left(9) == "textlarge")) && (arg.Right(1) == ":") )
                        {
                                if ( line.NumToken ( ' ' ) < 6 )
                                        m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Missing Argument for \"Text\""), false );
                                else
                                {
                                        CyString align = line.GetToken ( 5, ' ' ).ToLower();
                                        int iAlign = DT_CENTER;
                                        if ( align == "center" )
                                                iAlign = DT_CENTER;
                                        else if ( align == "left" )
                                                iAlign = DT_LEFT;
                                        else if ( align == "right" )
                                                iAlign = DT_RIGHT;
                                        else
                                                m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Invalid alignment setting \"") + align + "\"", false );

                                        LGTextSize iSize = LG_SMALL;
                                        if ( arg.Left(10) == "textmedium" )
                                                iSize = LG_MEDIUM;
                                        else if ( arg.Left(9) == "textsmall" )
                                                iSize = LG_SMALL;
                                        else if ( arg.Left(9) == "textlarge" )
                                                iSize = LG_BIG;

                                        bool scroll = false;
                                        if ( arg.Right (7) == "Scroll:" )
                                                scroll = true;

                                        int len = line.GetToken ( 4, ' ' ).ToInt();
                                        int x = line.GetToken ( 2, ' ' ).ToInt ();
                                        int y = line.GetToken ( 3, ' ' ).ToInt ();
                                        CyString str = line.GetToken ( 6, -1, ' ' );
                                        m_pHandles[iCurrentPos] = m_pLcd->AddText ( (scroll) ? LG_SCROLLING_TEXT : LG_STATIC_TEXT, iSize, iAlign, len );
                                        m_pLcd->SetOrigin ( m_pHandles[iCurrentPos], x, y );
                                        m_pLcd->SetText ( m_pHandles[iCurrentPos], (LPCTSTR)str.c_str() );

                                        SText *text = new SText;
                                        text->hObject = m_pHandles[iCurrentPos];
                                        text->sText = str;
                                        AddText ( text );
                                        iCurrentPos++;
                                }
                        }
                        else
                                m_lDebugLog.PushBack ( CyString((long)iLine) + CyString(": Invalid Command: ") + arg );

                        if ( iCurrentPos >= m_iArraySize )
                                IncreaseArraySize();
                }

                fclose ( id );
        }

        // debug
        m_pLcd->AddNewPage ();
    m_pLcd->ModifyControlsOnPage(m_iStartPage + 1);
        for ( int i = 0; i < 5; i++ )
        {
                m_hDebug[i] = m_pLcd->AddText ( LG_SCROLLING_TEXT, LG_SMALL, DT_LEFT, 160 );
                m_pLcd->SetOrigin ( m_hDebug, 0, (i * 9) );
        }

        if ( m_bDebug )
                m_iCycles = 100;

        return true;
}

void CLcdCustomScreen::SetVarible ( CyString v, int pos )
{
        if ( pos >= m_lVaribles.Count() )
                return;

        m_lVaribles.GetAt ( pos )->data = v;
}

void CLcdCustomScreen::Reset ()
{
        m_pLcd->RemovePage ( m_iStartPage + 1 );
        m_pLcd->RemovePage ( m_iStartPage );

        m_lDebugLog.Clear();
        m_lVaribles.Clear();

        SMoveObject *o = m_pMoveObject;
        while ( o )
        {
                SMoveObject *next = o->pNext;
                delete o;
                o = next;
        }

        SText *t = m_pText;
        while ( t )
        {
                SText *next = t->pNext;
                delete t;
                t = next;
        }
        m_pMoveObject = m_pEndMoveObject = NULL;
        m_pText = m_pEndText = NULL;
}

void CLcdCustomScreen::AddMoveObject ( SMoveObject *o )
{
        o->pNext = NULL;
        if ( !m_pEndMoveObject )
                m_pMoveObject = m_pEndMoveObject = o;
        else
        {
                m_pEndMoveObject->pNext = o;
                m_pEndMoveObject = o;
        }
}

void CLcdCustomScreen::AddText ( SText *t )
{
        t->pNext = NULL;
        if ( !m_pEndText )
                m_pText = m_pEndText = t;
        else
        {
                m_pEndText->pNext = t;
                m_pEndText = t;
        }
}

bool CLcdCustomScreen::Display ()
{
        --m_iCycles;

        if ( m_bDebug )
        {
                m_pLcd->ShowPage ( m_iStartPage + 1 );
            m_pLcd->ModifyControlsOnPage ( m_iStartPage + 1 );
                SStringList *str = m_lDebugLog.Head();
                for ( int i = 0; i < 5; i++ )
                {
                        if ( !str )
                                break;
                        m_pLcd->SetText ( m_hDebug[i], (LPCTSTR)str->str.c_str() );
                        str = str->next;
                }

                if ( !m_lDebugLog.Head() )
                        m_pLcd->SetText ( m_hDebug[0], _T("No errors found!") );
        }
        else
        {
                m_pLcd->ShowPage ( m_iStartPage );
            m_pLcd->ModifyControlsOnPage ( m_iStartPage );

                for ( SText *text = m_pText; text; text = text->pNext )
                {

                        CyString newtext = text->sText;
                        for ( SStringList *v = m_lVaribles.Head(); v; v = v->next )
                                newtext.FindReplace ( CyString("$") + v->str, v->data );
                        m_pLcd->SetText ( text->hObject, (LPCTSTR)newtext.c_str() );
                }

                // now do moving objects
                for ( SMoveObject *o = m_pMoveObject; o; o = o->pNext )
                {
                        if ( o->iTimeRemaining > 0 )
                                o->iTimeRemaining--;
                        else if ( o->bRepeat )
                                o->iTimeRemaining = o->iTotalTime;
                        
                        float t = (o->iTotalTime - o->iTimeRemaining)  / (float)o->iTotalTime;
                        float u = 1 - t;

                        int iX, iY;
                        if ( o->iStartX == o->iEndX ) iX = o->iStartX;
                        else                                              iX = (int)((double)((1 - t) * o->iStartX) + (t * o->iEndX));

                        if ( o->iStartY == o->iEndY ) iY = o->iStartY;
                        else                                              iY = (int)((double)((1 - t) * o->iStartY) + (t * o->iEndY));

                        m_pLcd->SetOrigin ( o->hObject, iX, iY );
                }
        }

        if ( m_iCycles > 0 )
                return true;
        return false;
}