228 lines
6.8 KiB
Text
228 lines
6.8 KiB
Text
// all them messages
|
|
|
|
Class DemolitionistChatTab : DemolitionistMenuTab
|
|
{
|
|
DemolitionistMenuList msglist;
|
|
int ofs, maxofs;
|
|
double smofs;
|
|
bool drag;
|
|
SWWMFullHistory hist;
|
|
|
|
override DemolitionistMenuTab Init( DemolitionistMenu master )
|
|
{
|
|
title = StringTable.Localize("$SWWM_CHATTAB");
|
|
hist = SWWMFullHistory.Get();
|
|
return Super.Init(master);
|
|
}
|
|
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( msglist ) msglist.Destroy();
|
|
}
|
|
|
|
override void OnSelect()
|
|
{
|
|
smofs = ofs;
|
|
}
|
|
override void OnDeselect()
|
|
{
|
|
smofs = ofs;
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
if ( !hist ) return;
|
|
int ypos = 0;
|
|
bool recenter = true;
|
|
if ( !msglist )
|
|
{
|
|
msglist = new("DemolitionistMenuList");
|
|
msglist.master = master;
|
|
msglist.selected = -1;
|
|
msglist.items.Resize(hist.msg.Size());
|
|
for ( int i=0; i<hist.msg.Size(); i++ )
|
|
{
|
|
msglist.items[i] = new("DemolitionistMenuChatItem").Init(master,hist.msg[i]);
|
|
msglist.items[i].ypos = ypos;
|
|
ypos += msglist.items[i].GetHeight();
|
|
}
|
|
}
|
|
else if ( msglist.items.Size() < hist.msg.Size() )
|
|
{
|
|
// theoretically we can assume that the message list will never shrink in the middle of gameplay, only grow
|
|
// also the array only ever has elements pushed, never inserted in-between
|
|
// if this somehow breaks, I don't know what the hell can do that
|
|
msglist.items.Resize(hist.msg.Size());
|
|
for ( int i=0; i<hist.msg.Size(); i++ )
|
|
{
|
|
if ( !msglist.items[i] )
|
|
{
|
|
msglist.items[i] = new("DemolitionistMenuChatItem").Init(master,hist.msg[i]);
|
|
msglist.items[i].ypos = ypos;
|
|
}
|
|
ypos += msglist.items[i].GetHeight();
|
|
}
|
|
if ( ofs < maxofs ) recenter = false; // don't recenter if we weren't at the bottom
|
|
}
|
|
else
|
|
{
|
|
for ( int i=0; i<msglist.items.Size(); i++ )
|
|
ypos += msglist.items[i].GetHeight();
|
|
recenter = false;
|
|
}
|
|
maxofs = max(ypos-int(master.ws.y-46),0);
|
|
// push it to the bottom
|
|
if ( recenter ) ofs = maxofs;
|
|
// update smooth scroll
|
|
smofs = (smofs*.6)+(ofs*.4);
|
|
if ( abs(smofs-ofs) < (1./master.hs) ) smofs = ofs;
|
|
// tick the list (not really needed, as elements don't dynamically update anything)
|
|
msglist.Ticker();
|
|
}
|
|
|
|
// called when sending a scroll input
|
|
// returns true if the position actually changed
|
|
// speed: how many pixels to move (either back or forward)
|
|
bool Scroll( int speed )
|
|
{
|
|
if ( maxofs <= 0 ) return false;
|
|
int oldofs = ofs;
|
|
ofs = clamp(ofs+speed,0,maxofs);
|
|
return (ofs != oldofs);
|
|
}
|
|
// called when clicking on our scrollbar
|
|
// returns true if the position actually changed
|
|
// y: relative click position
|
|
bool SetOffset( double y )
|
|
{
|
|
if ( maxofs <= 0 ) return false;
|
|
int oldofs = ofs;
|
|
ofs = clamp(int(round((y-20.5)/((master.ws.y-41.)/maxofs))),0,maxofs);
|
|
return (ofs != oldofs);
|
|
}
|
|
override void MenuInput( int key )
|
|
{
|
|
if ( maxofs <= 0 ) return;
|
|
switch ( key )
|
|
{
|
|
case MK_DOWN:
|
|
if ( Scroll(16) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
case MK_UP:
|
|
if ( Scroll(-16) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
}
|
|
}
|
|
override void MouseInput( Vector2 pos, int btn )
|
|
{
|
|
if ( maxofs <= 0 ) return;
|
|
switch ( btn )
|
|
{
|
|
case MB_LEFT:
|
|
// see if we're clicking the scrollbar (if it exists)
|
|
if ( pos.x > (master.ws.x-8) )
|
|
{
|
|
SetOffset(pos.y);
|
|
master.MenuSound("menu/demoscroll");
|
|
drag = true;
|
|
}
|
|
break;
|
|
case MB_WHEELUP:
|
|
if ( Scroll(-8) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
case MB_WHEELDOWN:
|
|
if ( Scroll(8) ) master.MenuSound("menu/demoscroll");
|
|
break;
|
|
case MB_DRAG:
|
|
if ( drag ) SetOffset(pos.y);
|
|
break;
|
|
case MB_RELEASE:
|
|
drag = false;
|
|
break;
|
|
}
|
|
}
|
|
override void Drawer()
|
|
{
|
|
if ( !hist || (msglist.items.Size() <= 0) )
|
|
{
|
|
String str = StringTable.Localize("$SWWM_NOCHAT");
|
|
double xx = int(master.ws.x-master.mSmallFont.StringWidth(str))/2;
|
|
double yy = int(master.ws.y-master.mSmallFont.GetHeight())/2;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
|
return;
|
|
}
|
|
double xx = 3;
|
|
double yy = 23;
|
|
int cliptop = int((master.origin.y+23)*master.hs);
|
|
int clipbottom = int((master.origin.y+master.ws.y-23)*master.hs);
|
|
int clipleft = int((master.origin.x+3)*master.hs);
|
|
int clipright = int((master.origin.x+master.ws.x-9)*master.hs);
|
|
msglist.Drawer((xx,yy-smofs),cliptop,clipbottom,clipleft,clipright);
|
|
if ( maxofs <= 0 ) return;
|
|
xx = master.ws.x-8;
|
|
master.DrawVSeparator(xx,14,master.ws.y-28);
|
|
xx += 2;
|
|
yy = floor(smofs*((master.ws.y-39)/maxofs))+14;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,"▮",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
|
}
|
|
}
|
|
|
|
// chat message item
|
|
Class DemolitionistMenuChatItem : DemolitionistMenuListItem
|
|
{
|
|
BrokenLines l;
|
|
int margin;
|
|
String tstamp;
|
|
|
|
DemolitionistMenuChatItem Init( DemolitionistMenu master, MsgLine m )
|
|
{
|
|
Super.Init(master,"");
|
|
if ( m.type == -1 )
|
|
{
|
|
// map change marker
|
|
label = String.Format("\cx[\c-%s\cx]\c-",m.str);
|
|
return self;
|
|
}
|
|
// actually use crimetime for the timestamps, for immersion
|
|
int rtime = (m.tic/GameTicRate)+(master.c_minute*60)+(master.c_hour*3600);
|
|
int thour = (rtime/3600)%24;
|
|
int tmin = (rtime/60)%60;
|
|
int tsec = rtime%60;
|
|
tstamp = String.Format("\cm[\c-%02d\cm:\c-%02d\cm:\c-%02d\cm]\c- ",thour,tmin,tsec);
|
|
margin = master.mSmallFont.StringWidth(tstamp);
|
|
l = master.mSmallFont.BreakLines(m.str,int(master.ws.x-14)-margin);
|
|
return self;
|
|
}
|
|
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( l ) l.Destroy();
|
|
}
|
|
|
|
override int GetWidth()
|
|
{
|
|
return int(master.ws.x-14);
|
|
}
|
|
|
|
override int GetHeight()
|
|
{
|
|
if ( l ) return l.Count()*14;
|
|
return 14;
|
|
}
|
|
|
|
override void Drawer( Vector2 pos, bool selected, int cliptop, int clipbottom, int clipleft, int clipright )
|
|
{
|
|
if ( !l )
|
|
{
|
|
// we'll assume this is a level change label
|
|
double xx = int((master.ws.x-14)-master.mSmallFont.StringWidth(label))/2;
|
|
Screen.DrawText(master.mSmallFont,Font.CR_GOLD,master.origin.x+pos.x+xx,master.origin.y+pos.y,label,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
|
|
return;
|
|
}
|
|
Screen.DrawText(master.mSmallFont,Font.CR_DARKGRAY,master.origin.x+pos.x,master.origin.y+pos.y,tstamp,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
|
|
for ( int i=0; i<l.Count(); i++ )
|
|
Screen.DrawText(master.mSmallFont,Font.CR_WHITE,master.origin.x+pos.x+margin,master.origin.y+pos.y+i*14,l.StringAt(i),DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
|
|
}
|
|
}
|