Adds ability for MLTextCtrl to type the characters out over time

This commit is contained in:
Areloch 2024-02-04 00:13:33 -06:00
parent b31a5eafe2
commit 6de92264f6
2 changed files with 93 additions and 12 deletions

View file

@ -224,6 +224,13 @@ DefineEngineMethod( GuiMLTextCtrl, forceReflow, void, (),,
object->reflow();
}
DefineEngineMethod(GuiMLTextCtrl, isTypingOut, bool, (), ,
"@brief Returns true if the text is being actively typed out.\n\n"
"@see GuiControl")
{
return object->isTypingOut();
}
//--------------------------------------------------------------------------
GuiMLTextCtrl::GuiMLTextCtrl()
: mTabStops( NULL ),
@ -264,7 +271,13 @@ GuiMLTextCtrl::GuiMLTextCtrl()
mDirty( true ),
mAlpha( 1.0f ),
mHitURL( 0 ),
mFontList( NULL )
mFontList( NULL ),
mUseTypeOverTime(false),
mTypeOverTimeStartMS(0),
mTypeOverTimeSpeedMS(10),
mTypeOverTimeIndex(0),
mTypeoutSoundRate(-1),
mTypeoutSound(nullptr)
{
mActive = true;
//mInitialText = StringTable->EmptyString();
@ -295,6 +308,11 @@ void GuiMLTextCtrl::initPersistFields()
addField("text", TypeCaseString, Offset( mInitialText, GuiMLTextCtrl ), "Text to display in this control.");
addField("useURLMouseCursor", TypeBool, Offset(mUseURLMouseCursor, GuiMLTextCtrl), "If true, the mouse cursor will turn into a hand cursor while over a link in the text.\n"
"This is dependant on the markup language used by the GuiMLTextCtrl\n");
addField("useTypeOverTime", TypeBool, Offset(mUseTypeOverTime, GuiMLTextCtrl), "");
addField("typeOverTimeSpeedMS", TypeF32, Offset(mTypeOverTimeSpeedMS, GuiMLTextCtrl), "");
addField("typeoutSound", TypeSFXTrackName, Offset(mTypeoutSound, GuiMLTextCtrl), "Played when the text is being typed out");
addField("typeoutSoundRate", TypeS32, Offset(mTypeoutSoundRate, GuiMLTextCtrl), "Dictates how many characters must be typed out before the sound is played again. -1 for the sound to only play once at the start.");
endGroup( "Text" );
@ -464,22 +482,46 @@ void GuiMLTextCtrl::onRender(Point2I offset, const RectI& updateRect)
for(Atom *awalk = lwalk->atomList; awalk; awalk = awalk->next)
{
if(!mSelectionActive || mSelectionEnd < awalk->textStart || mSelectionStart >= awalk->textStart + awalk->len)
drawAtomText(false, awalk->textStart, awalk->textStart + awalk->len, awalk, lwalk, offset);
if (mUseTypeOverTime)
{
F32 timeDif = Platform::getRealMilliseconds() - mTypeOverTimeStartMS;
if (timeDif > mTypeOverTimeSpeedMS)
{
//It's over the time increment, so update our index and next update timestamp start
mTypeOverTimeIndex++;
mTypeOverTimeStartMS = Platform::getRealMilliseconds();
if (mTypeoutSound)
{
if((mTypeoutSoundRate <= 0 && mTypeOverTimeIndex == 1) || mTypeOverTimeIndex % mTypeoutSoundRate > 0)
SFX->playOnce(mTypeoutSound);
}
}
U32 endPoint = getMin(awalk->textStart + awalk->len, mTypeOverTimeIndex);
endPoint = getMax(awalk->textStart, endPoint);
drawAtomText(false, awalk->textStart, endPoint, awalk, lwalk, offset);
}
else
{
U32 selectionStart = getMax(awalk->textStart, mSelectionStart);
U32 selectionEnd = getMin(awalk->textStart + awalk->len, mSelectionEnd + 1);
if (!mSelectionActive || mSelectionEnd < awalk->textStart || mSelectionStart >= awalk->textStart + awalk->len)
drawAtomText(false, awalk->textStart, awalk->textStart + awalk->len, awalk, lwalk, offset);
else
{
U32 selectionStart = getMax(awalk->textStart, mSelectionStart);
U32 selectionEnd = getMin(awalk->textStart + awalk->len, mSelectionEnd + 1);
// draw some unselected text
if(selectionStart > awalk->textStart)
drawAtomText(false, awalk->textStart, selectionStart, awalk, lwalk, offset);
// draw some unselected text
if (selectionStart > awalk->textStart)
drawAtomText(false, awalk->textStart, selectionStart, awalk, lwalk, offset);
// draw the selection
drawAtomText(true, selectionStart, selectionEnd, awalk, lwalk, offset);
// draw the selection
drawAtomText(true, selectionStart, selectionEnd, awalk, lwalk, offset);
if(selectionEnd < awalk->textStart + awalk->len)
drawAtomText(false, selectionEnd, awalk->textStart + awalk->len, awalk, lwalk, offset);
if (selectionEnd < awalk->textStart + awalk->len)
drawAtomText(false, selectionEnd, awalk->textStart + awalk->len, awalk, lwalk, offset);
}
}
}
}
@ -1678,6 +1720,12 @@ void GuiMLTextCtrl::reflow()
U32 idx;
U32 sizidx;
if (mUseTypeOverTime)
{
mTypeOverTimeStartMS = Platform::getRealMilliseconds();
mTypeOverTimeIndex = 1;
}
for(;;)
{
UTF16 curChar = mTextBuffer.getChar(mScanPos);
@ -2381,3 +2429,23 @@ bool GuiMLTextCtrl::resize( const Point2I& newPosition, const Point2I& newExtent
return false;
}
bool GuiMLTextCtrl::isTypingOut()
{
if (!mUseTypeOverTime)
return false;
U32 fullLength = 0;
for (Line* lwalk = mLineList; lwalk; lwalk = lwalk->next)
{
for (Atom* awalk = lwalk->atomList; awalk; awalk = awalk->next)
{
fullLength += awalk->len;
}
}
if (fullLength > mTypeOverTimeIndex)
return true;
return false;
}

View file

@ -99,6 +99,8 @@ class GuiMLTextCtrl : public GuiControl
Style *style;
bool isClipped;
U32 pauseTime;
URL *url;
Atom *next;
};
@ -264,6 +266,15 @@ class GuiMLTextCtrl : public GuiControl
// Too many chars sound:
DECLARE_SOUNDASSET(GuiMLTextCtrl, DeniedSound);
DECLARE_ASSET_SETGET(GuiMLTextCtrl, DeniedSound);
// Typeout over time
bool mUseTypeOverTime;
U32 mTypeOverTimeStartMS;
F32 mTypeOverTimeSpeedMS;
U32 mTypeOverTimeIndex;
U32 mTypeOverTimeTextLen;
SFXTrack *mTypeoutSound;
S32 mTypeoutSoundRate;
//-------------------------------------- Protected interface
protected:
// Inserting and deleting character blocks...
@ -304,6 +315,8 @@ class GuiMLTextCtrl : public GuiControl
S32 getCursorPosition() { return( mCursorPosition ); }
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
bool isTypingOut();
};
#endif // _H_GUIMLTEXTCTRL_