mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-11 13:11:47 +00:00
1618 lines
37 KiB
C++
1618 lines
37 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
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"
|
|
|
|
idSWFScriptObject_TextInstancePrototype textInstanceScriptObjectPrototype;
|
|
|
|
idCVar swf_textScrollSpeed( "swf_textScrollSpeed", "80", CVAR_INTEGER, "scroll speed for text" );
|
|
idCVar swf_textRndLetterSpeed( "swf_textRndLetterSpeed", "8", CVAR_INTEGER, "scroll speed for text" );
|
|
idCVar swf_textRndLetterDelay( "swf_textRndLetterDelay", "100", CVAR_INTEGER, "scroll speed for text" );
|
|
idCVar swf_textParagraphSpeed( "swf_textParagraphSpeed", "15", CVAR_INTEGER, "scroll speed for text" );
|
|
idCVar swf_textParagraphInc( "swf_textParagraphInc", "1.3", CVAR_FLOAT, "scroll speed for text" );
|
|
idCVar swf_subtitleExtraTime( "swf_subtitleExtraTime", "3500", CVAR_INTEGER, "time after subtitles vo is complete" );
|
|
idCVar swf_subtitleEarlyTrans( "swf_subtitleEarlyTrans", "3500", CVAR_INTEGER, "early time out to switch the line" );
|
|
idCVar swf_subtitleLengthGuess( "swf_subtitleLengthGuess", "10000", CVAR_INTEGER, "early time out to switch the line" );
|
|
idCVar swf_textMaxInputLength( "swf_textMaxInputLength", "104", CVAR_INTEGER, "max number of characters that can go into the input line" );
|
|
idCVar swf_textStrokeSize( "swf_textStrokeSize", "1.65f", CVAR_FLOAT, "size of font glyph stroke", 0.0f, 2.0f );
|
|
idCVar swf_textStrokeSizeGlyphSpacer( "swf_textStrokeSizeGlyphSpacer", "1.5f", CVAR_FLOAT, "additional space for spacing glyphs using stroke" );
|
|
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::idSWFTextInstance
|
|
========================
|
|
*/
|
|
idSWFTextInstance::idSWFTextInstance()
|
|
{
|
|
swf = NULL;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::~idSWFTextInstance
|
|
================== ======
|
|
*/
|
|
idSWFTextInstance::~idSWFTextInstance()
|
|
{
|
|
scriptObject.SetText( NULL );
|
|
scriptObject.Clear();
|
|
scriptObject.Release();
|
|
|
|
subtitleTimingInfo.Clear();
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::Init
|
|
========================
|
|
*/
|
|
void idSWFTextInstance::Init( idSWFEditText* _editText, idSWF* _swf )
|
|
{
|
|
editText = _editText;
|
|
swf = _swf;
|
|
|
|
text = idLocalization::GetString( editText->initialText );
|
|
|
|
lengthCalculated = false;
|
|
variable = editText->variable;
|
|
color = editText->color;
|
|
visible = true;
|
|
|
|
selectionStart = -1;
|
|
selectionEnd = -1;
|
|
|
|
scroll = 0;
|
|
scrollTime = 0;
|
|
maxscroll = 0;
|
|
maxLines = 0;
|
|
linespacing = 0;
|
|
glyphScale = 1.0f;
|
|
|
|
shiftHeld = false;
|
|
tooltip = false;
|
|
renderMode = SWF_TEXT_RENDER_NORMAL;
|
|
generatingText = false;
|
|
triggerGenerate = false;
|
|
rndSpotsVisible = 0;
|
|
textSpotsVisible = 0;
|
|
startRndTime = 0;
|
|
charMultiplier = 0;
|
|
prevReplaceIndex = 0;
|
|
scrollUpdate = false;
|
|
ignoreColor = false;
|
|
|
|
isSubtitle = false;
|
|
subLength = 0;
|
|
subAlign = 0;
|
|
subUpdating = false;
|
|
subCharStartIndex = 0;
|
|
subNextStartIndex = 0;
|
|
subCharEndIndex = 0;
|
|
subDisplayTime = 0;
|
|
subStartTime = -1;
|
|
subSourceID = -1;
|
|
subNeedsSwitch = false;
|
|
subForceKill = false;
|
|
subKillTimeDelay = 0;
|
|
subSwitchTime = 0;
|
|
subLastWordIndex = 0;
|
|
subPrevLastWordIndex = 0;
|
|
subInitialLine = true;
|
|
|
|
textLength = 0;
|
|
|
|
inputTextStartChar = 0;
|
|
|
|
renderDelay = swf_textRndLetterDelay.GetInteger();
|
|
needsSoundUpdate = false;
|
|
useDropShadow = false;
|
|
useStroke = false;
|
|
strokeStrength = 1.0f;
|
|
strokeWeight = swf_textStrokeSize.GetFloat();
|
|
|
|
scriptObject.SetPrototype( &textInstanceScriptObjectPrototype );
|
|
scriptObject.SetText( this );
|
|
scriptObject.SetNoAutoDelete( true );
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::GetTextLength
|
|
========================
|
|
*/
|
|
float idSWFTextInstance::GetTextLength()
|
|
{
|
|
// CURRENTLY ONLY WORKS FOR SINGLE LINE TEXTFIELDS
|
|
|
|
if( lengthCalculated && variable.IsEmpty() )
|
|
{
|
|
return textLength;
|
|
}
|
|
|
|
idStr txtLengthCheck = "";
|
|
|
|
float len = 0.0f;
|
|
if( verify( swf != NULL ) )
|
|
{
|
|
|
|
if( !variable.IsEmpty() )
|
|
{
|
|
idSWFScriptVar var = swf->GetGlobal( variable );
|
|
if( var.IsUndefined() )
|
|
{
|
|
txtLengthCheck = text;
|
|
}
|
|
else
|
|
{
|
|
txtLengthCheck = var.ToString();
|
|
}
|
|
txtLengthCheck = idLocalization::GetString( txtLengthCheck );
|
|
}
|
|
else
|
|
{
|
|
txtLengthCheck = idLocalization::GetString( text );
|
|
}
|
|
|
|
const idSWFEditText* shape = editText;
|
|
idSWFDictionaryEntry* fontEntry = swf->FindDictionaryEntry( shape->fontID, SWF_DICT_FONT );
|
|
idSWFFont* swfFont = fontEntry->font;
|
|
float width = fabs( shape->bounds.br.x - shape->bounds.tl.x );
|
|
float postTrans = SWFTWIP( shape->fontHeight );
|
|
const idFont* fontInfo = swfFont->fontID;
|
|
float glyphScale = postTrans / 48.0f;
|
|
|
|
int tlen = txtLengthCheck.Length();
|
|
int index = 0;
|
|
while( index < tlen )
|
|
{
|
|
scaledGlyphInfo_t glyph;
|
|
fontInfo->GetScaledGlyph( glyphScale, txtLengthCheck.UTF8Char( index ), glyph );
|
|
|
|
len += glyph.xSkip;
|
|
if( useStroke )
|
|
{
|
|
len += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * strokeWeight * glyphScale );
|
|
}
|
|
|
|
if( !( shape->flags & SWF_ET_AUTOSIZE ) && len >= width )
|
|
{
|
|
len = width;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
lengthCalculated = true;
|
|
textLength = len;
|
|
return textLength;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::StartParagraphText
|
|
========================
|
|
*/
|
|
void idSWFTextInstance::StartParagraphText( int time )
|
|
{
|
|
generatingText = true;
|
|
textSpotsVisible = 0;
|
|
randomtext = "";
|
|
triggerGenerate = false;
|
|
startRndTime = time;
|
|
rndTime = time;
|
|
rnd.SetSeed( time );
|
|
prevReplaceIndex = 0;
|
|
rndSpotsVisible = text.Length();
|
|
indexArray.Clear();
|
|
charMultiplier = 0;
|
|
|
|
text = idLocalization::GetString( text );
|
|
lengthCalculated = false;
|
|
|
|
for( int index = 0; index < text.Length(); ++index )
|
|
{
|
|
randomtext.Append( " " );
|
|
indexArray.Append( index );
|
|
}
|
|
|
|
for( int index = 0; index < indexArray.Num(); ++index )
|
|
{
|
|
int swapIndex = rnd.RandomInt( indexArray.Num() );
|
|
int val = indexArray[index];
|
|
indexArray[index] = indexArray[swapIndex];
|
|
indexArray[swapIndex] = val;
|
|
}
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::GetParagraphText
|
|
========================
|
|
*/
|
|
idStr idSWFTextInstance::GetParagraphText( int time )
|
|
{
|
|
if( triggerGenerate )
|
|
{
|
|
return " ";
|
|
}
|
|
else if( time - startRndTime < renderDelay )
|
|
{
|
|
return " ";
|
|
}
|
|
else if( generatingText )
|
|
{
|
|
if( time - rndTime >= renderDelay )
|
|
{
|
|
rndTime = time;
|
|
needsSoundUpdate = true;
|
|
|
|
if( prevReplaceIndex >= text.Length() )
|
|
{
|
|
generatingText = false;
|
|
return text;
|
|
}
|
|
|
|
randomtext[prevReplaceIndex] = text[prevReplaceIndex];
|
|
prevReplaceIndex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scrollUpdate = false;
|
|
return text;
|
|
}
|
|
|
|
return randomtext;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::StartRandomText
|
|
========================
|
|
*/
|
|
bool idSWFTextInstance::NeedsSoundPlayed()
|
|
{
|
|
if( soundClip.IsEmpty() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return needsSoundUpdate;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::StartRandomText
|
|
========================
|
|
*/
|
|
void idSWFTextInstance::StartRandomText( int time )
|
|
{
|
|
generatingText = true;
|
|
textSpotsVisible = 0;
|
|
randomtext = "";
|
|
triggerGenerate = false;
|
|
startRndTime = time;
|
|
rndTime = time;
|
|
rnd.SetSeed( time );
|
|
rndSpotsVisible = 0;
|
|
|
|
text = idLocalization::GetString( text );
|
|
lengthCalculated = false;
|
|
|
|
for( int index = 0; index < text.Length(); ++index )
|
|
{
|
|
if( text[index] == ' ' )
|
|
{
|
|
randomtext.Append( " " );
|
|
}
|
|
else
|
|
{
|
|
randomtext.Append( "." );
|
|
rndSpotsVisible++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFTextInstance::GetRandomText
|
|
========================
|
|
*/
|
|
idStr idSWFTextInstance::GetRandomText( int time )
|
|
{
|
|
|
|
if( triggerGenerate )
|
|
{
|
|
return " ";
|
|
}
|
|
else if( time - startRndTime < renderDelay )
|
|
{
|
|
return " ";
|
|
}
|
|
else if( generatingText )
|
|
{
|
|
if( rndSpotsVisible > 0 )
|
|
{
|
|
|
|
int waitTime = swf_textRndLetterSpeed.GetInteger();
|
|
|
|
if( randomtext.Length() >= 10 )
|
|
{
|
|
waitTime = waitTime / 3;
|
|
}
|
|
|
|
if( time - rndTime >= waitTime )
|
|
{
|
|
rndTime = time;
|
|
|
|
int spotIndex = rnd.RandomInt( rndSpotsVisible );
|
|
int cIndex = 0;
|
|
for( int c = 0; c < randomtext.Length(); ++ c )
|
|
{
|
|
|
|
if( c >= text.Length() )
|
|
{
|
|
rndSpotsVisible = 0;
|
|
break;
|
|
}
|
|
|
|
if( randomtext[c] == '.' )
|
|
{
|
|
cIndex++;
|
|
}
|
|
|
|
if( cIndex == spotIndex )
|
|
{
|
|
|
|
bool useCaps = false;
|
|
|
|
if( c - 1 >= 0 && text[c - 1] == ' ' )
|
|
{
|
|
useCaps = true;
|
|
}
|
|
else if( c == 0 )
|
|
{
|
|
useCaps = true;
|
|
}
|
|
|
|
if( useCaps || renderMode == SWF_TEXT_RENDER_RANDOM_APPEAR_CAPS )
|
|
{
|
|
randomtext[c] = rnd.RandomInt( 'Z' - 'A' ) + 'A';
|
|
}
|
|
else
|
|
{
|
|
randomtext[c] = rnd.RandomInt( 'z' - 'a' ) + 'a';
|
|
}
|
|
|
|
rndSpotsVisible--;
|
|
if( !soundClip.IsEmpty() )
|
|
{
|
|
needsSoundUpdate = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( rndSpotsVisible == 0 && textSpotsVisible < text.Length() )
|
|
{
|
|
if( textSpotsVisible >= randomtext.Length() )
|
|
{
|
|
textSpotsVisible++;
|
|
}
|
|
else
|
|
{
|
|
if( time - rndTime >= swf_textRndLetterSpeed.GetInteger() )
|
|
{
|
|
rndTime = time;
|
|
randomtext[textSpotsVisible] = text[textSpotsVisible];
|
|
textSpotsVisible++;
|
|
if( !soundClip.IsEmpty() )
|
|
{
|
|
needsSoundUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return " ";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return text;
|
|
}
|
|
|
|
if( rndSpotsVisible == 0 && textSpotsVisible == text.Length() )
|
|
{
|
|
generatingText = false;
|
|
}
|
|
|
|
return randomtext;
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
SUBTITLE FUNCTIONALITY
|
|
==============================================
|
|
*/
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::SwitchSubtitleText
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::SwitchSubtitleText( int time )
|
|
{
|
|
subNeedsSwitch = false;
|
|
}
|
|
|
|
void idSWFTextInstance::SetSubNextStartIndex( int value )
|
|
{
|
|
subNextStartIndex = value;
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::UpdateSubtitle
|
|
==============================================
|
|
*/
|
|
bool idSWFTextInstance::UpdateSubtitle( int time )
|
|
{
|
|
|
|
if( subForceKillQueued )
|
|
{
|
|
subForceKillQueued = false;
|
|
subForceKill = true;
|
|
subKillTimeDelay = time + swf_subtitleExtraTime.GetInteger();
|
|
}
|
|
|
|
if( subUpdating && !subForceKill )
|
|
{
|
|
if( ( time >= subSwitchTime && !subNeedsSwitch ) || ( !subNeedsSwitch && subInitialLine ) )
|
|
{
|
|
//idLib::Printf( "SWITCH TIME %d / %d \n", time, subSwitchTime );
|
|
|
|
if( subInitialLine && subtitleTimingInfo.Num() > 0 )
|
|
{
|
|
if( subStartTime == -1 )
|
|
{
|
|
subStartTime = time - 600;
|
|
}
|
|
if( time < subStartTime + subtitleTimingInfo[0].startTime )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
text = subtitleText;//subtitleText = "";
|
|
subInitialLine = false;
|
|
}
|
|
}
|
|
|
|
if( subNextStartIndex + 1 >= text.Length( ) )
|
|
{
|
|
subForceKillQueued = true;
|
|
}
|
|
else
|
|
{
|
|
subCharStartIndex = subNextStartIndex;
|
|
//subtitleText.CopyRange( text, subCharStartIndex, subCharEndIndex );
|
|
subNeedsSwitch = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( subForceKill )
|
|
{
|
|
if( time >= subKillTimeDelay )
|
|
{
|
|
subForceKill = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::SubtitleComplete
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::SetSubEndIndex( int endChar, int time )
|
|
{
|
|
subCharEndIndex = endChar;
|
|
if( subCharEndIndex + 1 >= text.Length() )
|
|
{
|
|
LastWordChanged( subtitleTimingInfo.Num(), time );
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::SubtitleComplete
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::SubtitleComplete()
|
|
{
|
|
subInitialLine = true;
|
|
subUpdating = false;
|
|
isSubtitle = false;
|
|
subNeedsSwitch = false;
|
|
subCharDisplayTime = 0;
|
|
subForceKillQueued = false;
|
|
subForceKill = false;
|
|
subKillTimeDelay = 0;
|
|
subSwitchTime = 0;
|
|
subLastWordIndex = 0;
|
|
subPrevLastWordIndex = 0;
|
|
subStartTime = -1;
|
|
subSpeaker = "";
|
|
subtitleText = "";
|
|
text = "";
|
|
subtitleTimingInfo.Clear();
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::LastWordChanged
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::LastWordChanged( int wordCount, int time )
|
|
{
|
|
if( subPrevLastWordIndex + wordCount >= subtitleTimingInfo.Num() )
|
|
{
|
|
subLastWordIndex = subtitleTimingInfo.Num() - 1;
|
|
}
|
|
else
|
|
{
|
|
subLastWordIndex = subPrevLastWordIndex + wordCount - 1;
|
|
}
|
|
|
|
if( subStartTime == -1 )
|
|
{
|
|
if( subtitleTimingInfo.Num() > 0 )
|
|
{
|
|
subStartTime = time + subtitleTimingInfo[0].startTime;
|
|
}
|
|
else
|
|
{
|
|
subStartTime = time;
|
|
}
|
|
}
|
|
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[subLastWordIndex].startTime;// - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 1 %d last word %d\n", subSwitchTime, subLastWordIndex );
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::GetSubtitleBreak
|
|
==============================================
|
|
*/
|
|
int idSWFTextInstance::GetApporoximateSubtitleBreak( int time )
|
|
{
|
|
|
|
int wordIndex = subLastWordIndex;
|
|
bool setSwitchTime = false;
|
|
|
|
if( subStartTime == -1 )
|
|
{
|
|
subStartTime = time;
|
|
}
|
|
|
|
if( time >= subSwitchTime )
|
|
{
|
|
subPrevLastWordIndex = subLastWordIndex;
|
|
for( int i = wordIndex; i < subtitleTimingInfo.Num(); ++i )
|
|
{
|
|
if( subtitleTimingInfo[i].forceBreak )
|
|
{
|
|
if( i + 1 < subtitleTimingInfo.Num() )
|
|
{
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[i + 1].startTime; // - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 2 %d\n", subSwitchTime );
|
|
subLastWordIndex = i;
|
|
setSwitchTime = true;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[i].startTime;// - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 3 %d\n", subSwitchTime );
|
|
subLastWordIndex = i;
|
|
setSwitchTime = true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int timeSpan = subtitleTimingInfo[i].startTime - subtitleTimingInfo[wordIndex].startTime;
|
|
if( timeSpan > swf_subtitleLengthGuess.GetInteger() )
|
|
{
|
|
if( i - 1 >= 0 )
|
|
{
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[i].startTime;// - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 4 %d\n", subSwitchTime );
|
|
subLastWordIndex = i - 1;
|
|
}
|
|
else
|
|
{
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[i].startTime;// - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 5 %d\n", subSwitchTime );
|
|
subLastWordIndex = i;
|
|
}
|
|
setSwitchTime = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !setSwitchTime && subtitleTimingInfo.Num() > 0 )
|
|
{
|
|
subSwitchTime = subStartTime + subtitleTimingInfo[ subtitleTimingInfo.Num() - 1 ].startTime;// - swf_subtitleEarlyTrans.GetInteger();
|
|
//idLib::Printf( "switchtime set 6 %d\n", subSwitchTime );
|
|
subLastWordIndex = subtitleTimingInfo.Num();
|
|
}
|
|
}
|
|
|
|
return subLastWordIndex;
|
|
}
|
|
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::SubtitleComplete
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::SubtitleCleanup()
|
|
{
|
|
subSourceID = -1;
|
|
subAlign = -1;
|
|
text = "";
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::SetStrokeInfo
|
|
==============================================
|
|
*/
|
|
void idSWFTextInstance::SetStrokeInfo( bool use, float strength, float weight )
|
|
{
|
|
useStroke = use;
|
|
if( use )
|
|
{
|
|
strokeWeight = weight;
|
|
strokeStrength = strength;
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================================
|
|
idSWFTextInstance::CalcMaxScroll
|
|
==============================================
|
|
*/
|
|
int idSWFTextInstance::CalcMaxScroll( int numLines )
|
|
{
|
|
|
|
if( numLines != -1 )
|
|
{
|
|
if( numLines < 0 )
|
|
{
|
|
numLines = 0;
|
|
}
|
|
maxscroll = numLines;
|
|
return maxscroll;
|
|
}
|
|
|
|
const idSWFEditText* shape = editText;
|
|
if( !( shape->flags & SWF_ET_MULTILINE ) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if( swf == NULL )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
idSWFDictionaryEntry* fontEntry = swf->FindDictionaryEntry( shape->fontID, SWF_DICT_FONT );
|
|
if( fontEntry == NULL )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
idSWFFont* swfFont = fontEntry->font;
|
|
if( swfFont == NULL )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
const idFont* fontInfo = swfFont->fontID;
|
|
if( fontInfo == NULL )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
idStr textCheck;
|
|
if( variable.IsEmpty() )
|
|
{
|
|
textCheck = idLocalization::GetString( text );
|
|
}
|
|
else
|
|
{
|
|
textCheck = idLocalization::GetString( variable );
|
|
}
|
|
|
|
if( textCheck.IsEmpty() )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float x = bounds.tl.x;
|
|
float y = bounds.tl.y;
|
|
|
|
idList< idStr > textLines;
|
|
idStr* currentLine = &textLines.Alloc();
|
|
|
|
// tracks the last breakable character we found
|
|
int lastbreak = 0;
|
|
float lastbreakX = 0;
|
|
int charIndex = 0;
|
|
|
|
if( IsSubtitle() )
|
|
{
|
|
charIndex = GetSubStartIndex();
|
|
}
|
|
|
|
while( charIndex < textCheck.Length() )
|
|
{
|
|
if( textCheck[ charIndex ] == '\n' )
|
|
{
|
|
if( shape->flags & SWF_ET_MULTILINE )
|
|
{
|
|
currentLine->Append( '\n' );
|
|
x = bounds.tl.x;
|
|
y += linespacing;
|
|
currentLine = &textLines.Alloc();
|
|
lastbreak = 0;
|
|
charIndex++;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
int glyphStart = charIndex;
|
|
uint32 tc = textCheck.UTF8Char( charIndex );
|
|
scaledGlyphInfo_t glyph;
|
|
fontInfo->GetScaledGlyph( glyphScale, tc, glyph );
|
|
float glyphSkip = glyph.xSkip;
|
|
if( HasStroke() )
|
|
{
|
|
glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * GetStrokeWeight() * glyphScale );
|
|
}
|
|
|
|
if( x + glyphSkip > bounds.br.x )
|
|
{
|
|
if( shape->flags & ( SWF_ET_MULTILINE | SWF_ET_WORDWRAP ) )
|
|
{
|
|
if( lastbreak > 0 )
|
|
{
|
|
int curLineIndex = currentLine - &textLines[0];
|
|
idStr* newline = &textLines.Alloc();
|
|
currentLine = &textLines[ curLineIndex ];
|
|
if( maxLines == 1 )
|
|
{
|
|
currentLine->CapLength( currentLine->Length() - 3 );
|
|
currentLine->Append( "..." );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
*newline = currentLine->c_str() + lastbreak;
|
|
currentLine->CapLength( lastbreak );
|
|
currentLine = newline;
|
|
x -= lastbreakX;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currentLine = &textLines.Alloc();
|
|
x = bounds.tl.x;
|
|
}
|
|
lastbreak = 0;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
while( glyphStart < charIndex && glyphStart < text.Length() )
|
|
{
|
|
currentLine->Append( text[ glyphStart++ ] );
|
|
}
|
|
x += glyphSkip;
|
|
if( tc == ' ' || tc == '-' )
|
|
{
|
|
lastbreak = currentLine->Length();
|
|
lastbreakX = x;
|
|
}
|
|
}
|
|
|
|
maxscroll = textLines.Num() - maxLines;
|
|
if( maxscroll < 0 )
|
|
{
|
|
maxscroll = 0;
|
|
}
|
|
return maxscroll;
|
|
}
|
|
|
|
int idSWFTextInstance::CalcNumLines()
|
|
{
|
|
|
|
const idSWFEditText* shape = editText;
|
|
if( !( shape->flags & SWF_ET_MULTILINE ) )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
idSWFDictionaryEntry* fontEntry = swf->FindDictionaryEntry( shape->fontID, SWF_DICT_FONT );
|
|
if( fontEntry == NULL )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
idStr textCheck;
|
|
|
|
if( variable.IsEmpty() )
|
|
{
|
|
textCheck = idLocalization::GetString( text );
|
|
}
|
|
else
|
|
{
|
|
textCheck = idLocalization::GetString( variable );
|
|
}
|
|
|
|
if( textCheck.IsEmpty() )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if( swf == NULL )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
idSWFFont* swfFont = fontEntry->font;
|
|
float postTransformHeight = SWFTWIP( shape->fontHeight );
|
|
const idFont* fontInfo = swfFont->fontID;
|
|
|
|
float glyphScale = postTransformHeight / 48.0f;
|
|
|
|
swfRect_t bounds;
|
|
bounds.tl.x = ( shape->bounds.tl.x + SWFTWIP( shape->leftMargin ) );
|
|
bounds.br.x = ( shape->bounds.br.x - SWFTWIP( shape->rightMargin ) );
|
|
bounds.tl.y = ( shape->bounds.tl.y + ( 1.15f * glyphScale ) );
|
|
bounds.br.y = ( shape->bounds.br.y );
|
|
|
|
float linespacing = fontInfo->GetAscender( 1.15f * glyphScale );
|
|
if( shape->leading != 0 )
|
|
{
|
|
linespacing += ( glyphScale * SWFTWIP( shape->leading ) );
|
|
}
|
|
|
|
float x = bounds.tl.x;
|
|
int maxLines = idMath::Ftoi( ( bounds.br.y - bounds.tl.y ) / linespacing );
|
|
if( maxLines == 0 )
|
|
{
|
|
maxLines = 1;
|
|
}
|
|
|
|
// tracks the last breakable character we found
|
|
int numLines = 1;
|
|
int lastbreak = 0;
|
|
int charIndex = 0;
|
|
|
|
while( charIndex < textCheck.Length() )
|
|
{
|
|
if( textCheck[ charIndex ] == '\n' )
|
|
{
|
|
if( numLines == maxLines )
|
|
{
|
|
return maxLines;
|
|
}
|
|
numLines++;
|
|
lastbreak = 0;
|
|
x = bounds.tl.x;
|
|
charIndex++;
|
|
}
|
|
else
|
|
{
|
|
uint32 tc = textCheck[ charIndex++ ];
|
|
scaledGlyphInfo_t glyph;
|
|
fontInfo->GetScaledGlyph( glyphScale, tc, glyph );
|
|
|
|
float glyphSkip = glyph.xSkip;
|
|
if( useStroke )
|
|
{
|
|
glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * strokeWeight * glyphScale );
|
|
}
|
|
|
|
if( x + glyphSkip > bounds.br.x )
|
|
{
|
|
if( numLines == maxLines )
|
|
{
|
|
return maxLines;
|
|
}
|
|
else
|
|
{
|
|
numLines++;
|
|
if( lastbreak != 0 )
|
|
{
|
|
charIndex = charIndex - ( charIndex - lastbreak );
|
|
}
|
|
x = bounds.tl.x;
|
|
lastbreak = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
x += glyphSkip;
|
|
if( tc == ' ' || tc == '-' )
|
|
{
|
|
lastbreak = charIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return numLines;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idSWFScriptObject_TextInstancePrototype
|
|
========================
|
|
*/
|
|
|
|
#define SWF_TEXT_FUNCTION_DEFINE( x ) idSWFScriptVar idSWFScriptObject_TextInstancePrototype::idSWFScriptFunction_##x::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms )
|
|
#define SWF_TEXT_NATIVE_VAR_DEFINE_GET( x ) idSWFScriptVar idSWFScriptObject_TextInstancePrototype::idSWFScriptNativeVar_##x::Get( class idSWFScriptObject * object )
|
|
#define SWF_TEXT_NATIVE_VAR_DEFINE_SET( x ) void idSWFScriptObject_TextInstancePrototype::idSWFScriptNativeVar_##x::Set( class idSWFScriptObject * object, const idSWFScriptVar & value )
|
|
|
|
#define SWF_TEXT_PTHIS_FUNC( x ) idSWFTextInstance * pThis = thisObject ? thisObject->GetText() : NULL; if ( !verify( pThis != NULL ) ) { idLib::Warning( "SWF: tried to call " x " on NULL edittext" ); return idSWFScriptVar(); }
|
|
#define SWF_TEXT_PTHIS_GET( x ) idSWFTextInstance * pThis = object ? object->GetText() : NULL; if ( pThis == NULL ) { return idSWFScriptVar(); }
|
|
#define SWF_TEXT_PTHIS_SET( x ) idSWFTextInstance * pThis = object ? object->GetText() : NULL; if ( pThis == NULL ) { return; }
|
|
|
|
#define SWF_TEXT_FUNCTION_SET( x ) scriptFunction_##x.AddRef(); Set( #x, &scriptFunction_##x );
|
|
#define SWF_TEXT_NATIVE_VAR_SET( x ) SetNative( #x, &swfScriptVar_##x );
|
|
|
|
idSWFScriptObject_TextInstancePrototype::idSWFScriptObject_TextInstancePrototype()
|
|
{
|
|
|
|
SWF_TEXT_FUNCTION_SET( onKey );
|
|
SWF_TEXT_FUNCTION_SET( onChar );
|
|
SWF_TEXT_FUNCTION_SET( generateRnd );
|
|
SWF_TEXT_FUNCTION_SET( calcNumLines );
|
|
SWF_TEXT_FUNCTION_SET( clearTimingInfo );
|
|
|
|
SWF_TEXT_NATIVE_VAR_SET( text );
|
|
SWF_TEXT_NATIVE_VAR_SET( _textLength ); // only works on single lines of text not multiline
|
|
SWF_TEXT_NATIVE_VAR_SET( autoSize );
|
|
SWF_TEXT_NATIVE_VAR_SET( dropShadow );
|
|
SWF_TEXT_NATIVE_VAR_SET( _stroke );
|
|
SWF_TEXT_NATIVE_VAR_SET( _strokeStrength );
|
|
SWF_TEXT_NATIVE_VAR_SET( _strokeWeight );
|
|
SWF_TEXT_NATIVE_VAR_SET( variable );
|
|
SWF_TEXT_NATIVE_VAR_SET( _alpha );
|
|
SWF_TEXT_NATIVE_VAR_SET( textColor );
|
|
SWF_TEXT_NATIVE_VAR_SET( _visible );
|
|
SWF_TEXT_NATIVE_VAR_SET( selectionStart );
|
|
SWF_TEXT_NATIVE_VAR_SET( selectionEnd );
|
|
SWF_TEXT_NATIVE_VAR_SET( scroll );
|
|
SWF_TEXT_NATIVE_VAR_SET( maxscroll );
|
|
SWF_TEXT_NATIVE_VAR_SET( isTooltip );
|
|
SWF_TEXT_NATIVE_VAR_SET( mode );
|
|
SWF_TEXT_NATIVE_VAR_SET( delay );
|
|
SWF_TEXT_NATIVE_VAR_SET( renderSound );
|
|
SWF_TEXT_NATIVE_VAR_SET( updateScroll );
|
|
SWF_TEXT_NATIVE_VAR_SET( subtitle );
|
|
SWF_TEXT_NATIVE_VAR_SET( subtitleAlign );
|
|
SWF_TEXT_NATIVE_VAR_SET( subtitleSourceID );
|
|
SWF_TEXT_NATIVE_VAR_SET( subtitleSpeaker );
|
|
|
|
SWF_TEXT_FUNCTION_SET( subtitleSourceCheck );
|
|
SWF_TEXT_FUNCTION_SET( subtitleStart );
|
|
SWF_TEXT_FUNCTION_SET( subtitleLength );
|
|
SWF_TEXT_FUNCTION_SET( killSubtitle );
|
|
SWF_TEXT_FUNCTION_SET( forceKillSubtitle );
|
|
SWF_TEXT_FUNCTION_SET( subLastLine );
|
|
SWF_TEXT_FUNCTION_SET( addSubtitleInfo );
|
|
SWF_TEXT_FUNCTION_SET( terminateSubtitle );
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( text )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "text" );
|
|
return pThis->text;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( text )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "text " );
|
|
pThis->text = idLocalization::GetString( value.ToString() );
|
|
if( pThis->text.IsEmpty() )
|
|
{
|
|
pThis->selectionEnd = -1;
|
|
pThis->selectionStart = -1;
|
|
pThis->inputTextStartChar = 0;
|
|
}
|
|
pThis->lengthCalculated = false;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( autoSize )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "autoSize" );
|
|
return ( pThis->editText->flags & SWF_ET_AUTOSIZE ) != 0;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( autoSize )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "autoSize" );
|
|
if( value.ToBool() )
|
|
{
|
|
pThis->editText->flags |= SWF_ET_AUTOSIZE;
|
|
}
|
|
else
|
|
{
|
|
pThis->editText->flags &= ~SWF_ET_AUTOSIZE;
|
|
}
|
|
pThis->lengthCalculated = false;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( dropShadow )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "dropShadow" );
|
|
return pThis->useDropShadow;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( dropShadow )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "dropShadow" );
|
|
pThis->useDropShadow = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _stroke )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_stroke" );
|
|
return pThis->useStroke;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( _stroke )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "_stroke" );
|
|
pThis->useStroke = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _strokeStrength )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_strokeStrength" );
|
|
return pThis->strokeStrength;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( _strokeStrength )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "_strokeStrength" );
|
|
pThis->strokeStrength = value.ToFloat();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _strokeWeight )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_strokeWeight" );
|
|
return pThis->strokeWeight;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( _strokeWeight )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "_strokeWeight" );
|
|
pThis->strokeWeight = value.ToFloat();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( variable )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "variable" );
|
|
return pThis->variable;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( variable )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "variable" );
|
|
pThis->variable = value.ToString();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _alpha )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_alpha" );
|
|
return pThis->color.a / 255.0f;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( _alpha )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "_alpha" );
|
|
pThis->color.a = idMath::Ftob( value.ToFloat() * 255.0f );
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _visible )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_visible" );
|
|
return pThis->visible;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( _visible )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "_visible" );
|
|
pThis->visible = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( selectionStart )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "selectionStart" );
|
|
return pThis->selectionStart;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( selectionStart )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "selectionStart" );
|
|
pThis->selectionStart = value.ToInteger();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( selectionEnd )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "selectionEnd" );
|
|
return pThis->selectionEnd;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( selectionEnd )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "selectionEnd" );
|
|
pThis->selectionEnd = value.ToInteger();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( isTooltip )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "isTooltip" );
|
|
pThis->tooltip = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( isTooltip )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "isTooltip" );
|
|
return pThis->tooltip;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( delay )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "delay" );
|
|
pThis->renderDelay = value.ToInteger();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( delay )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "delay" );
|
|
return pThis->renderDelay;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( renderSound )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "renderSound" );
|
|
pThis->soundClip = value.ToString();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( renderSound )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "renderSound" );
|
|
return pThis->soundClip;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( updateScroll )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "updateScroll" );
|
|
pThis->scrollUpdate = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( updateScroll )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "updateScroll" );
|
|
return pThis->scrollUpdate;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( mode )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "mode" );
|
|
return pThis->renderMode;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( scroll )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "scroll" );
|
|
return pThis->scroll;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( maxscroll )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "maxscroll" );
|
|
return pThis->maxscroll;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( _textLength )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "_textLength" );
|
|
return pThis->GetTextLength();
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( mode )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "mode" );
|
|
|
|
int mode = value.ToInteger();
|
|
|
|
if( mode >= ( int )SWF_TEXT_RENDER_MODE_COUNT || mode < 0 )
|
|
{
|
|
mode = SWF_TEXT_RENDER_NORMAL;
|
|
}
|
|
|
|
pThis->renderMode = swfTextRenderMode_t( mode );
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( scroll )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "scroll" );
|
|
|
|
int time = Sys_Milliseconds();
|
|
if( time >= pThis->scrollTime )
|
|
{
|
|
pThis->scrollTime = Sys_Milliseconds() + swf_textScrollSpeed.GetInteger();
|
|
pThis->scroll = value.ToInteger();
|
|
}
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( maxscroll )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "maxscroll" );
|
|
pThis->maxscroll = value.ToInteger();
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( textColor )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "textColor" );
|
|
|
|
int r = ( pThis->color.r << 16 );
|
|
int g = ( pThis->color.g << 8 );
|
|
int b = pThis->color.b;
|
|
|
|
int textColor = r | g | b;
|
|
|
|
return textColor;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( textColor )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "textColor" );
|
|
|
|
int textColor = value.ToInteger();
|
|
int r = ( textColor >> 16 ) & 0xFF;
|
|
int g = ( textColor >> 8 ) & 0x00FF;
|
|
int b = textColor & 0x0000FF;
|
|
|
|
pThis->color.r = r;
|
|
pThis->color.g = g;
|
|
pThis->color.b = b;
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( clearTimingInfo )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "clearTimingInfo" );
|
|
pThis->subtitleTimingInfo.Clear();
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( generateRnd )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "generateRnd" );
|
|
pThis->triggerGenerate = true;
|
|
pThis->rndSpotsVisible = -1;
|
|
pThis->generatingText = false;
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( calcNumLines )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "calcNumLines" );
|
|
|
|
return pThis->CalcNumLines();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( onKey )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "onKey" );
|
|
|
|
int keyCode = parms[0].ToInteger();
|
|
bool keyDown = parms[1].ToBool();
|
|
|
|
if( keyDown )
|
|
{
|
|
switch( keyCode )
|
|
{
|
|
case K_LSHIFT:
|
|
case K_RSHIFT:
|
|
{
|
|
pThis->shiftHeld = true;
|
|
break;
|
|
}
|
|
case K_BACKSPACE:
|
|
case K_DEL:
|
|
{
|
|
if( pThis->selectionStart == pThis->selectionEnd )
|
|
{
|
|
if( keyCode == K_BACKSPACE )
|
|
{
|
|
pThis->selectionStart = pThis->selectionEnd - 1;
|
|
}
|
|
else
|
|
{
|
|
pThis->selectionEnd = pThis->selectionStart + 1;
|
|
}
|
|
}
|
|
int start = Min( pThis->selectionStart, pThis->selectionEnd );
|
|
int end = Max( pThis->selectionStart, pThis->selectionEnd );
|
|
idStr left = pThis->text.Left( Max( start, 0 ) );
|
|
idStr right = pThis->text.Right( Max( pThis->text.Length() - end, 0 ) );
|
|
pThis->text = left + right;
|
|
pThis->selectionStart = start;
|
|
pThis->selectionEnd = start;
|
|
break;
|
|
}
|
|
case K_LEFTARROW:
|
|
{
|
|
if( pThis->selectionEnd > 0 )
|
|
{
|
|
pThis->selectionEnd--;
|
|
if( !pThis->shiftHeld )
|
|
{
|
|
pThis->selectionStart = pThis->selectionEnd;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case K_RIGHTARROW:
|
|
{
|
|
if( pThis->selectionEnd < pThis->text.Length() )
|
|
{
|
|
pThis->selectionEnd++;
|
|
if( !pThis->shiftHeld )
|
|
{
|
|
pThis->selectionStart = pThis->selectionEnd;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case K_HOME:
|
|
{
|
|
pThis->selectionEnd = 0;
|
|
if( !pThis->shiftHeld )
|
|
{
|
|
pThis->selectionStart = pThis->selectionEnd;
|
|
}
|
|
break;
|
|
}
|
|
case K_END:
|
|
{
|
|
pThis->selectionEnd = pThis->text.Length();
|
|
if( !pThis->shiftHeld )
|
|
{
|
|
pThis->selectionStart = pThis->selectionEnd;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( keyCode == K_LSHIFT || keyCode == K_RSHIFT )
|
|
{
|
|
pThis->shiftHeld = false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( onChar )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "onChar" );
|
|
|
|
int keyCode = parms[0].ToInteger();
|
|
|
|
if( keyCode < 32 || keyCode == 127 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
char letter = ( char )keyCode;
|
|
// assume ` is meant for the console
|
|
if( letter == '`' )
|
|
{
|
|
return false;
|
|
}
|
|
if( pThis->selectionStart != pThis->selectionEnd )
|
|
{
|
|
int start = Min( pThis->selectionStart, pThis->selectionEnd );
|
|
int end = Max( pThis->selectionStart, pThis->selectionEnd );
|
|
idStr left = pThis->text.Left( Max( start, 0 ) );
|
|
idStr right = pThis->text.Right( Max( pThis->text.Length() - end, 0 ) );
|
|
pThis->text = left + right;
|
|
pThis->selectionStart = start;
|
|
|
|
pThis->text.Clear();
|
|
pThis->text.Append( left );
|
|
pThis->text.Append( letter );
|
|
pThis->text.Append( right );
|
|
pThis->selectionStart++;
|
|
}
|
|
else if( pThis->selectionStart < swf_textMaxInputLength.GetInteger() )
|
|
{
|
|
if( pThis->selectionStart < 0 )
|
|
{
|
|
pThis->selectionStart = 0;
|
|
}
|
|
pThis->text.Insert( letter, pThis->selectionStart++ );
|
|
}
|
|
pThis->selectionEnd = pThis->selectionStart;
|
|
return true;
|
|
}
|
|
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( subtitle )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "subtitle" );
|
|
return pThis->isSubtitle;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( subtitle )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "subtitle" );
|
|
pThis->isSubtitle = value.ToBool();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( subtitleAlign )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "subtitleAlign" );
|
|
return pThis->subAlign;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( subtitleAlign )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "subtitleAlign" );
|
|
pThis->subAlign = value.ToInteger();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( subtitleSourceID )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "subtitleSourceID" );
|
|
return pThis->subSourceID;
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( subtitleSourceID )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "subtitleSourceID" );
|
|
pThis->subSourceID = value.ToInteger();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_GET( subtitleSpeaker )
|
|
{
|
|
SWF_TEXT_PTHIS_GET( "subtitleSpeaker" );
|
|
return pThis->subSpeaker.c_str();
|
|
}
|
|
SWF_TEXT_NATIVE_VAR_DEFINE_SET( subtitleSpeaker )
|
|
{
|
|
SWF_TEXT_PTHIS_SET( "subtitleSpeaker" );
|
|
pThis->subSpeaker = value.ToString();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( subtitleLength )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "subtitleLength" );
|
|
pThis->subLength = parms[0].ToInteger();
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( subtitleSourceCheck )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "subtitleSourceCheck" );
|
|
|
|
int idCheck = parms[0].ToInteger();
|
|
|
|
if( pThis->subSourceID == -1 )
|
|
{
|
|
pThis->subSourceID = idCheck;
|
|
return 1;
|
|
}
|
|
|
|
if( idCheck == pThis->subSourceID ) // || pThis->subForceKill ) {
|
|
{
|
|
pThis->SubtitleComplete();
|
|
pThis->subSourceID = idCheck;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( subtitleStart )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "subtitleStart" );
|
|
pThis->subUpdating = true;
|
|
pThis->subNeedsSwitch = false;
|
|
pThis->subForceKillQueued = false;
|
|
pThis->subForceKill = false;
|
|
pThis->subKillTimeDelay = 0;
|
|
// trickery to swap the text so subtitles don't show until they should
|
|
pThis->subtitleText = pThis->text;
|
|
pThis->text = "";
|
|
pThis->subCharStartIndex = 0;
|
|
pThis->subNextStartIndex = 0;
|
|
pThis->subCharEndIndex = 0;
|
|
pThis->subSwitchTime = 0;
|
|
pThis->subLastWordIndex = 0;
|
|
pThis->subPrevLastWordIndex = 0;
|
|
pThis->subStartTime = -1;
|
|
pThis->subInitialLine = true;
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( forceKillSubtitle )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "forceKillSubtitle" );
|
|
pThis->subForceKill = true;
|
|
pThis->subKillTimeDelay = 0;
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( killSubtitle )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "killSubtitle" );
|
|
pThis->subForceKillQueued = true;
|
|
//pThis->SubtitleComplete();
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( terminateSubtitle )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "terminateSubtitle" );
|
|
pThis->SubtitleComplete();
|
|
pThis->SubtitleCleanup();
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( subLastLine )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "subLastLine" );
|
|
idStr lastLine;
|
|
int len = pThis->subCharEndIndex - pThis->subCharStartIndex;
|
|
pThis->text.Mid( pThis->subCharStartIndex, len, lastLine );
|
|
return lastLine;
|
|
}
|
|
|
|
SWF_TEXT_FUNCTION_DEFINE( addSubtitleInfo )
|
|
{
|
|
SWF_TEXT_PTHIS_FUNC( "addSubtitleInfo" );
|
|
|
|
if( parms.Num() != 3 )
|
|
{
|
|
return idSWFScriptVar();
|
|
}
|
|
|
|
subTimingWordData_t info;
|
|
info.phrase = parms[0].ToString();
|
|
info.startTime = parms[1].ToInteger();
|
|
info.forceBreak = parms[2].ToBool();
|
|
|
|
pThis->subtitleTimingInfo.Append( info );
|
|
return idSWFScriptVar();
|
|
}
|