etqw-sdk/source/game/guis/UICreditScroll.cpp

313 lines
7.9 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "UIWindow.h"
#include "UserInterfaceLocal.h"
#include "UICreditScroll.h"
#include "../../sys/sys_local.h"
SD_UI_IMPLEMENT_CLASS( sdUICreditScroll, sdUIWindow )
idHashMap< sdUITemplateFunction< sdUICreditScroll >* > sdUICreditScroll::creditFunctions;
/*
============
sdUICreditScroll::sdUICreditScroll
============
*/
sdUICreditScroll::sdUICreditScroll( void ) :
items( NULL ),
totalHeight( 0.0f ),
scrollStartTime( 0 ),
scrollTargetTime( 0 ) {
scriptState.GetProperties().RegisterProperty( "speed", speed );
speed = 5.0f;
scrollOffset = 0.0f;
SetWindowFlag( WF_CLIP_TO_RECT );
}
/*
============
sdUICreditScroll::~sdUICreditScroll
============
*/
sdUICreditScroll::~sdUICreditScroll( void ) {
DisconnectGlobalCallbacks();
ClearItems();
}
/*
============
sdUICreditScroll::ClearItems
============
*/
void sdUICreditScroll::ClearItems() {
while( items != NULL ) {
sdCreditItem* next = items->next;
delete items;
items = next;
}
}
/*
============
sdUICreditScroll::GetFunction
============
*/
sdUIFunctionInstance* sdUICreditScroll::GetFunction( const char* name ) {
const sdUITemplateFunction< sdUICreditScroll >* function = sdUICreditScroll::FindFunction( name );
if( !function ) {
return sdUIWindow::GetFunction( name );
}
return new sdUITemplateFunctionInstance< sdUICreditScroll, sdUITemplateFunctionInstance_IdentifierTimeline >( this, function );
}
/*
============
sdUICreditScroll::FindFunction
============
*/
const sdUITemplateFunction< sdUICreditScroll >* sdUICreditScroll::FindFunction( const char* name ) {
sdUITemplateFunction< sdUICreditScroll >** ptr;
return creditFunctions.Get( name, &ptr ) ? *ptr : NULL;
}
/*
============
sdUICreditScroll::InitFunctions
============
*/
SD_UI_PUSH_CLASS_TAG( sdUICreditScroll )
void sdUICreditScroll::InitFunctions() {
SD_UI_FUNC_TAG( resetScroll, "Reset scroll amount." )
SD_UI_END_FUNC_TAG
creditFunctions.Set( "resetScroll", new sdUITemplateFunction< sdUICreditScroll >( 'v', "", &sdUICreditScroll::Script_ResetScroll ) );
SD_UI_FUNC_TAG( loadFromFile, "Load the text to scroll from a file. Supports UTF8." )
SD_UI_FUNC_PARM( string, "filePath", "File to load data from." )
SD_UI_END_FUNC_TAG
creditFunctions.Set( "loadFromFile",new sdUITemplateFunction< sdUICreditScroll >( 'v', "s", &sdUICreditScroll::Script_LoadFromFile ) );
}
SD_UI_POP_CLASS_TAG
/*
============
sdUICreditScroll::Script_ResetScroll
============
*/
void sdUICreditScroll::Script_ResetScroll( sdUIFunctionStack& stack ) {
scrollOffset = 0.0f;
}
/*
============
sdUICreditScroll::DrawLocal
============
*/
void sdUICreditScroll::DrawLocal() {
const sdCreditItem* item = items;
sdBounds2D bounds( cachedClientRect );
while( item != NULL ) {
sdBounds2D b( item->rect );
b.TranslateSelf( 0.0f, scrollOffset );
if( b.IntersectsBounds( bounds ) ) {
if( item->material.material != NULL ) {
deviceContext->DrawMaterial( item->rect.x, item->rect.y + scrollOffset, item->rect.z, item->rect.w, item->material.material, item->color, item->material.st0, item->material.st1 );
} else {
deviceContext->SetColor( item->color );
deviceContext->SetFontSize( fontSize + item->fontSize );
deviceContext->DrawText( item->text.c_str(), b, DTF_TOP | DTF_SINGLELINE | DTF_CENTER );
}
}
item = item->next;
}
}
/*
============
sdUICreditScroll::Script_LoadFromFile
============
*/
void sdUICreditScroll::Script_LoadFromFile( sdUIFunctionStack& stack ) {
ClearItems();
idStr fileName;
stack.Pop( fileName );
sdFilePtr file( fileSystem->OpenFileRead( fileName.c_str() ) );
if( !file.IsValid() ) {
gameLocal.Warning( "%s: Script_LoadFromFile: could not find '%s'", name.GetValue().c_str(), fileName.c_str() );
return;
}
sdUTF8 utf8( file.Get() );
file.Release();
int numChars = utf8.DecodeLength();
wchar_t* ucs2 = static_cast< wchar_t* >( Mem_Alloc( ( numChars + 1 ) * sizeof( wchar_t ) ) );
utf8.Decode( ucs2 );
idWLexer src( ucs2, idWStr::Length( ucs2 ), fileName );
if ( !src.IsLoaded() ) {
Mem_Free( ucs2 );
return;
}
declManager->AddDependency( GetUI()->GetDecl(), fileName.c_str() );
lastItem = NULL;
idWToken token;
while( src.ReadToken( &token ) ) {
int i = token.linesCrossed;
while( i > 1 ) {
sdCreditItem* item = new sdCreditItem;
item->rect.w = 8.0f;
Append( item );
i--;
}
sdCreditItem* item = new sdCreditItem;
bool needText = false;
bool useText = true;
if( token.Cmp( L"material" ) == 0 ) {
idWToken w;
idWToken h;
src.ReadToken( &w );
src.ReadToken( &h );
src.ReadToken( &token );
GetUI()->LookupMaterial( va( "%ls", token.c_str() ), item->material );
assert( w.type == TT_NUMBER );
assert( h.type == TT_NUMBER );
item->rect.z = w.GetFloatValue();
item->rect.w = h.GetFloatValue();
useText = false;
item->color = colorWhite;
} else if( token.Icmp( L"small" ) == 0 ) {
item->fontSize = -2;
needText = true;
item->color = colorWhite;
} else if( token.Icmp( L"big" ) == 0 ) {
item->fontSize = 2;
item->color = colorWhite;
needText = true;
} else if( token.Icmp( L"huge" ) == 0 ) {
item->fontSize = 4;
item->color = colorWhite;
needText = true;
}
if( needText ) {
src.ReadToken( &token );
}
if( useText ) {
assert( token.type == TT_STRING );
item->text = token.c_str();
}
Append( item );
}
MakeLayoutDirty();
}
/*
============
sdUICreditScroll::Append
============
*/
void sdUICreditScroll::Append( sdCreditItem* item ) {
if( items == NULL ) {
items = item;
} else if( lastItem != NULL ) {
lastItem->next = item;
}
lastItem = item;
}
/*
============
sdUICreditScroll::ApplyLayout
============
*/
void sdUICreditScroll::ApplyLayout() {
bool apply = windowState.recalculateLayout;
sdUIWindow::ApplyLayout();
if( apply ) {
float yOffset = 0.0f;
sdBounds2D measureRect( 0.0f, 0.0f, cachedClientRect.z * 0.33f, SCREEN_HEIGHT );
int w;
int h;
ActivateFont( true );
sdCreditItem* item = items;
while( item != NULL ) {
if( item->material.material != NULL ) {
item->rect.x = cachedClientRect.x + ( cachedClientRect.z * 0.5f ) - ( item->rect.z * 0.5f );
item->rect.y = cachedClientRect.y + yOffset;
} else if( !item->text.IsEmpty() ) {
deviceContext->SetFontSize( fontSize + item->fontSize );
deviceContext->GetTextDimensions( item->text.c_str(), measureRect, DTF_SINGLELINE | DTF_CENTER | DTF_TOP, cachedFontHandle, fontSize + item->fontSize, w, h );
item->rect.x = cachedClientRect.x + ( cachedClientRect.z * 0.5f ) - ( w * 0.5f );
item->rect.y = cachedClientRect.y + yOffset;
item->rect.z = w;
item->rect.w = h;
}
yOffset += item->rect.w;
item = item->next;
}
totalHeight = yOffset;
scrollOffset = cachedClientRect.w;
scrollStartTime = 0;
scrollTargetTime = 0;
}
const int now = GetUI()->GetCurrentTime();
float ratio = totalHeight / cachedClientRect.w;
if ( ratio < 1.0f ) {
ratio = 1.0f;
}
if ( now >= scrollTargetTime || scrollStartTime == scrollTargetTime || now < scrollStartTime ) {
scrollStartTime = now;
}
scrollTargetTime = scrollStartTime + SEC2MS( speed * ratio );
float totalTime = static_cast< float >( scrollTargetTime - scrollStartTime );
float percent = static_cast< float >( now - scrollStartTime ) / totalTime;
scrollOffset = cachedClientRect.w - percent * ( cachedClientRect.w + totalHeight );
if( idMath::Fabs( scrollOffset ) >= totalHeight ) {
scrollOffset = cachedClientRect.w;
}
}