SpaceCadetPinballPPC/SpaceCadetPinball/TTextBox.cpp
2021-10-04 17:04:09 +03:00

263 lines
4.8 KiB
C++

#include "pch.h"
#include "TTextBox.h"
#include "control.h"
#include "fullscrn.h"
#include "loader.h"
#include "render.h"
#include "score.h"
#include "timer.h"
TTextBox::TTextBox(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true)
{
OffsetX = 0;
OffsetY = 0;
Width = 0;
Height = 0;
BgBmp = render::background_bitmap;
Font = score::msg_fontp;
Message1 = nullptr;
Message2 = nullptr;
Timer = 0;
if (groupIndex > 0)
{
/*Full tilt: text box dimensions index is offset by resolution*/
int arrLength;
auto dimensions = loader::query_iattribute(groupIndex + fullscrn::GetResolution(), 1500, &arrLength);
OffsetX = dimensions[0];
OffsetY = dimensions[1];
Width = dimensions[2];
Height = dimensions[3];
}
}
TTextBox::~TTextBox()
{
if (Timer)
{
if (Timer != -1)
timer::kill(Timer);
Timer = 0;
}
while (Message1)
{
TTextBoxMessage* message = Message1;
TTextBoxMessage* nextMessage = message->NextMessage;
delete message;
Message1 = nextMessage;
}
}
int TTextBox::Message(int code, float value)
{
return 0;
}
void TTextBox::TimerExpired(int timerId, void* caller)
{
auto tb = static_cast<TTextBox*>(caller);
TTextBoxMessage* message = tb->Message1;
tb->Timer = 0;
if (message)
{
TTextBoxMessage* nextMessage = message->NextMessage;
delete message;
tb->Message1 = nextMessage;
tb->Draw();
control::handler(60, tb);
}
}
void TTextBox::Clear()
{
gdrv_bitmap8* bmp = BgBmp;
if (bmp)
gdrv::copy_bitmap(
render::vscreen,
Width,
Height,
OffsetX,
OffsetY,
bmp,
OffsetX,
OffsetY);
else
gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0);
if (Timer)
{
if (Timer != -1)
timer::kill(Timer);
Timer = 0;
}
while (Message1)
{
TTextBoxMessage* message = Message1;
TTextBoxMessage* nextMessage = message->NextMessage;
delete message;
Message1 = nextMessage;
}
}
void TTextBox::Display(const char* text, float time)
{
if (!text)
return;
if (Message1 && !strcmp(text, Message2->Text))
{
Message2->Refresh(time);
if (Message2 == Message1)
{
if (Timer && Timer != -1)
timer::kill(Timer);
if (time == -1.0f)
Timer = -1;
else
Timer = timer::set(time, this, TimerExpired);
}
}
else
{
if (Timer == -1)
Clear();
auto message = new TTextBoxMessage(text, time);
if (message)
{
if (message->Text)
{
if (Message1)
Message2->NextMessage = message;
else
Message1 = message;
Message2 = message;
if (Timer == 0)
Draw();
}
else
{
delete message;
}
}
}
}
void TTextBox::Draw()
{
auto bmp = BgBmp;
if (bmp)
gdrv::copy_bitmap(
render::vscreen,
Width,
Height,
OffsetX,
OffsetY,
bmp,
OffsetX,
OffsetY);
else
gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0);
bool display = false;
while (Message1)
{
if (Message1->Time == -1.0f)
{
if (!Message1->NextMessage)
{
Timer = -1;
display = true;
break;
}
}
else if (Message1->TimeLeft() >= -2.0f)
{
Timer = timer::set(std::max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
display = true;
break;
}
auto tmp = Message1;
Message1 = Message1->NextMessage;
delete tmp;
}
if (display)
{
auto font = Font;
if (!font)
{
gdrv::grtext_draw_ttext_in_box(
Message1->Text,
render::vscreen->XPosition + OffsetX,
render::vscreen->YPosition + OffsetY,
Width,
Height,
255);
return;
}
auto text = Message1->Text;
for (auto y = OffsetY; ; y += font->Height)
{
auto curChar = *text;
if (!curChar || y + font->Height > OffsetY + Height)
break;
auto totalWidth = 0;
char* textEndSpace = nullptr;
auto textEnd = text;
while (true)
{
auto maskedChar = curChar & 0x7F;
if (!maskedChar || maskedChar == '\n')
break;
auto charBmp = font->Chars[maskedChar];
if (charBmp)
{
auto width = charBmp->Width + font->GapWidth + totalWidth;
if (width > Width)
{
if (textEndSpace)
textEnd = textEndSpace;
break;
}
if (*textEnd == ' ')
textEndSpace = textEnd;
curChar = *(textEnd + 1);
totalWidth = width;
++textEnd;
}
else
{
curChar = *textEnd;
}
}
auto offX = OffsetX;
while (text < textEnd)
{
auto charBmp = font->Chars[*text++ & 0x7F];
if (charBmp)
{
auto height = charBmp->Height;
auto width = charBmp->Width;
if (render::background_bitmap)
gdrv::copy_bitmap_w_transparency(render::vscreen, width, height, offX, y, charBmp, 0,
0);
else
gdrv::copy_bitmap(render::vscreen, width, height, offX, y, charBmp, 0, 0);
font = Font;
offX += charBmp->Width + font->GapWidth;
}
}
while ((*text & 0x7F) == ' ')
++text;
if ((*text & 0x7F) == '\n')
++text;
}
}
}