Library partially implemented (mouse support pending).
This commit is contained in:
parent
8122b21af1
commit
d3725d855e
52 changed files with 1672 additions and 957 deletions
|
|
@ -325,21 +325,16 @@ Class DemolitionistMenuInvItem : DemolitionistMenuListItem
|
|||
Class DemolitionistMenuLoreItem : DemolitionistMenuListItem
|
||||
{
|
||||
SWWMLore ent;
|
||||
bool bActive; // currently being read
|
||||
|
||||
DemolitionistMenuLoreItem Init( DemolitionistMenu master, SWWMLore e )
|
||||
{
|
||||
Super.Init(master,"");
|
||||
ent = e;
|
||||
label = StringTable.Localize(ent.tag);
|
||||
return self;
|
||||
}
|
||||
|
||||
// return true if this entry hasn't been read yet
|
||||
// used for the "unread" indicators on the top bar
|
||||
bool IsUnread()
|
||||
{
|
||||
return !ent.read;
|
||||
}
|
||||
|
||||
// marks this entry as read
|
||||
void MarkRead()
|
||||
{
|
||||
|
|
@ -347,9 +342,11 @@ Class DemolitionistMenuLoreItem : DemolitionistMenuListItem
|
|||
EventHandler.SendNetworkEvent(String.Format("swwmmarkloreread.%s",ent.tag),consoleplayer);
|
||||
}
|
||||
|
||||
String GetText()
|
||||
override void Drawer( Vector2 pos, bool selected, int cliptop, int clipbottom, int clipleft, int clipright )
|
||||
{
|
||||
return StringTable.Localize(ent.text);
|
||||
String str = label;
|
||||
if ( !ent.read ) str = "\cf‼\c-"..label;
|
||||
Screen.DrawText(smallfont,bActive?Font.CR_FIRE:selected?Font.CR_WHITE:Font.CR_DARKGRAY,master.origin.x+pos.x,master.origin.y+pos.y,str,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Class DemolitionistMenuTextBox ui
|
|||
DemolitionistMenu master;
|
||||
String txt;
|
||||
BrokenLines l;
|
||||
TextureID img;
|
||||
int ofs;
|
||||
int x, w;
|
||||
bool scrollbar;
|
||||
|
|
@ -32,6 +33,32 @@ Class DemolitionistMenuTextBox ui
|
|||
}
|
||||
return self;
|
||||
}
|
||||
// allow changing contents without re-creating the class
|
||||
void Reinit( String txt, int x = 0, int w = 0 )
|
||||
{
|
||||
String oldtxt = self.txt;
|
||||
self.txt = txt;
|
||||
self.x = x;
|
||||
int oldw = self.w;
|
||||
if ( w == 0 ) self.w = 640-x;
|
||||
else self.w = w;
|
||||
// break lines again (if changed)
|
||||
if ( (self.w == oldw) && (self.txt == oldtxt) ) return;
|
||||
if ( l ) l.Destroy();
|
||||
l = smallfont.BreakLines(self.txt,self.w-12);
|
||||
int h = l.Count()*13;
|
||||
if ( h > (master.ws.y-34) )
|
||||
{
|
||||
l.Destroy();
|
||||
l = smallfont.BreakLines(self.txt,self.w-20);
|
||||
scrollbar = true;
|
||||
maxofs = int((l.Count()*13)-(master.ws.y-34));
|
||||
}
|
||||
// restrict scroll (if changed)
|
||||
if ( ofs > maxofs ) smofs = ofs = maxofs;
|
||||
// reset scroll if text is different
|
||||
if ( self.txt != oldtxt ) smofs = ofs = 0;
|
||||
}
|
||||
override void OnDestroy()
|
||||
{
|
||||
l.Destroy();
|
||||
|
|
@ -70,6 +97,13 @@ Class DemolitionistMenuTextBox ui
|
|||
double yy = 17-smofs;
|
||||
int miny = int((master.origin.y+17)*master.hs);
|
||||
int maxy = int((master.origin.y+(master.ws.y-17))*master.hs);
|
||||
// draw image if defined and visible
|
||||
if ( img.IsValid() )
|
||||
{
|
||||
Vector2 imgsz = TexMan.GetScaledSize(img);
|
||||
if ( (yy+imgsz.y >= 17) && (yy < master.ws.y) )
|
||||
Screen.DrawTexture(img,false,master.origin.x+xx,master.origin.y+yy,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true,DTA_ClipTop,miny,DTA_ClipBottom,maxy);
|
||||
}
|
||||
for ( int i=0; i<l.Count(); i++, yy+=13 )
|
||||
{
|
||||
// to save time, we skip lines that aren't visible
|
||||
|
|
|
|||
|
|
@ -2,9 +2,310 @@
|
|||
|
||||
Class DemolitionistLibraryTab : DemolitionistMenuTab
|
||||
{
|
||||
DemolitionistMenuList lists[4];
|
||||
int section;
|
||||
String sname[4];
|
||||
int lwidth;
|
||||
SWWMLoreLibrary lore;
|
||||
int loresz;
|
||||
int ofs[4], maxofs[4];
|
||||
double smofs[4];
|
||||
bool drag;
|
||||
int sel[4];
|
||||
DemolitionistMenuLoreItem active;
|
||||
SWWMLore clore;
|
||||
DemolitionistMenuTextBox ltext;
|
||||
|
||||
private int partition_lore( Array<DemolitionistMenuListItem> a, int l, int h )
|
||||
{
|
||||
DemolitionistMenuListItem pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( StringTable.Localize(DemolitionistMenuLoreItem(pv).ent.tag) > StringTable.Localize(DemolitionistMenuLoreItem(a[j]).ent.tag) )
|
||||
{
|
||||
i++;
|
||||
DemolitionistMenuListItem tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
DemolitionistMenuListItem tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_lore( Array<DemolitionistMenuListItem> a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_lore(a,l,h);
|
||||
qsort_lore(a,l,p-1);
|
||||
qsort_lore(a,p+1,h);
|
||||
}
|
||||
|
||||
override DemolitionistMenuTab Init( DemolitionistMenu master )
|
||||
{
|
||||
title = "$SWWM_KBASETAB";
|
||||
lore = SWWMLoreLibrary.Find(players[consoleplayer]);
|
||||
section = 0;
|
||||
lwidth = 0;
|
||||
for ( int i=0; i<4; i++ )
|
||||
{
|
||||
sname[i] = StringTable.Localize("$SWWM_LORETAB"..i);
|
||||
lwidth = max(lwidth,smallfont.StringWidth("<‼ "..sname[i].." ‼>")+6);
|
||||
lists[i] = new("DemolitionistMenuList");
|
||||
lists[i].master = master;
|
||||
lists[i].selected = 0;
|
||||
}
|
||||
loresz = lore.ent.Size();
|
||||
for ( int i=0; i<loresz; i++ )
|
||||
{
|
||||
let ent = lore.ent[i];
|
||||
let le = new("DemolitionistMenuLoreItem").Init(master,ent);
|
||||
lists[ent.tab].items.Push(le);
|
||||
lwidth = max(lwidth,smallfont.StringWidth("‼"..le.label)+6);
|
||||
}
|
||||
for ( int i=0; i<4; i++ )
|
||||
{
|
||||
qsort_lore(lists[i].items,0,lists[i].items.Size()-1);
|
||||
maxofs[i] = max(0,lists[i].items.Size()*13-(master.ws.y-50));
|
||||
for ( int j=0; j<lists[i].items.Size(); j++ )
|
||||
lists[i].items[j].ypos = j*13;
|
||||
}
|
||||
return Super.Init(master);
|
||||
}
|
||||
override void OnDestroy()
|
||||
{
|
||||
for ( int i=0; i<4; i++ )
|
||||
lists[i].Destroy();
|
||||
if ( ltext ) ltext.Destroy();
|
||||
}
|
||||
override void OnSelect()
|
||||
{
|
||||
section = master.shnd.menustate.At("LastLoreSection").ToInt();
|
||||
smofs[section] = ofs[section];
|
||||
}
|
||||
override void OnDeselect()
|
||||
{
|
||||
master.shnd.menustate.Insert("LastLoreSection",String.Format("%d",section));
|
||||
smofs[section] = ofs[section];
|
||||
}
|
||||
override void Ticker()
|
||||
{
|
||||
// update library (if anything changes)
|
||||
if ( lore.ent.Size() > loresz )
|
||||
{
|
||||
int olwidth = lwidth;
|
||||
// append the new entries
|
||||
for ( int i=loresz; i<lore.ent.Size(); i++ )
|
||||
{
|
||||
let ent = lore.ent[i];
|
||||
let le = new("DemolitionistMenuLoreItem").Init(master,ent);
|
||||
lists[ent.tab].items.Push(le);
|
||||
lwidth = max(lwidth,smallfont.StringWidth("‼"..le.label)+6);
|
||||
}
|
||||
// re-sort the lists, ensuring we are still selecting the same entry
|
||||
for ( int i=0; i<4; i++ )
|
||||
{
|
||||
if ( lists[i].items.Size() <= 0 ) continue;
|
||||
let osel = lists[i].items[lists[i].selected];
|
||||
qsort_lore(lists[i].items,0,lists[i].items.Size()-1);
|
||||
let idx = lists[i].items.Find(osel);
|
||||
if ( (idx != lists[i].items.Size()) && (idx != lists[i].selected) )
|
||||
{
|
||||
sel[i] = lists[i].selected = idx;
|
||||
KBScroll();
|
||||
}
|
||||
maxofs[i] = max(0,lists[i].items.Size()*13-(master.ws.y-50));
|
||||
if ( ofs[i] > maxofs[i] ) smofs[i] = ofs[i] = maxofs[i];
|
||||
for ( int j=0; j<lists[i].items.Size(); j++ )
|
||||
lists[i].items[j].ypos = j*13;
|
||||
}
|
||||
loresz = lore.ent.Size();
|
||||
// append the notification for new lore
|
||||
master.tmsg = StringTable.Localize("$SWWM_NEWLORE");
|
||||
master.tmsgtic = gametic+70;
|
||||
if ( (lwidth != olwidth) && clore && ltext )
|
||||
ltext.Reinit(StringTable.Localize(clore.text),lwidth+((maxofs[section]>0)?8:0));
|
||||
}
|
||||
// update smooth scroll
|
||||
smofs[section] = (smofs[section]*.6)+(ofs[section]*.4);
|
||||
if ( abs(smofs[section]-ofs[section]) < (1./master.hs) ) smofs[section] = ofs[section];
|
||||
// tick the current list
|
||||
lists[section].Ticker();
|
||||
// tick the text box
|
||||
if ( ltext ) ltext.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[section] <= 0 ) return false;
|
||||
int oldofs = ofs[section];
|
||||
ofs[section] = clamp(ofs[section]+speed,0,maxofs[section]);
|
||||
return (ofs[section] != oldofs);
|
||||
}
|
||||
// called when clicking on our scrollbar
|
||||
// returns true if the position actually changed
|
||||
// y: relative click position
|
||||
bool SetOffset( double y )
|
||||
{
|
||||
if ( maxofs[section] <= 0 ) return false;
|
||||
int oldofs = ofs[section];
|
||||
ofs[section] = clamp(int(round((y-20.5)/((master.ws.y-41.)/maxofs[section]))),0,maxofs[section]);
|
||||
return (ofs[section] != oldofs);
|
||||
}
|
||||
// called when keyboard scrolling
|
||||
void KBScroll()
|
||||
{
|
||||
if ( maxofs[section] <= 0 ) return;
|
||||
int miny = (lists[section].selected+1)*13-(master.ws.y-50);
|
||||
int maxy = lists[section].selected*13;
|
||||
if ( ofs[section] < miny ) ofs[section] = clamp(miny,0,maxofs[section]);
|
||||
else if ( ofs[section] > maxy ) ofs[section] = clamp(maxy,0,maxofs[section]);
|
||||
}
|
||||
override void MenuInput( int key )
|
||||
{
|
||||
switch ( key )
|
||||
{
|
||||
case MK_LEFT:
|
||||
int prev = max(0,section-1);
|
||||
while ( prev > 0 )
|
||||
{
|
||||
if ( lists[prev].items.Size() > 0 )
|
||||
break;
|
||||
prev--;
|
||||
}
|
||||
if ( prev == section ) break;
|
||||
master.MenuSound("menu/demoscroll");
|
||||
smofs[section] = ofs[section];
|
||||
section = prev;
|
||||
smofs[section] = ofs[section];
|
||||
if ( clore && ltext )
|
||||
ltext.Reinit(StringTable.Localize(clore.text),lwidth+((maxofs[section]>0)?8:0));
|
||||
break;
|
||||
case MK_RIGHT:
|
||||
int next = min(3,section+1);
|
||||
while ( next < 3 )
|
||||
{
|
||||
if ( lists[next].items.Size() > 0 )
|
||||
break;
|
||||
next++;
|
||||
}
|
||||
if ( next == section ) break;
|
||||
master.MenuSound("menu/demoscroll");
|
||||
smofs[section] = ofs[section];
|
||||
section = next;
|
||||
smofs[section] = ofs[section];
|
||||
if ( clore && ltext )
|
||||
ltext.Reinit(StringTable.Localize(clore.text),lwidth+((maxofs[section]>0)?8:0));
|
||||
break;
|
||||
case MK_DOWN:
|
||||
if ( clore && ltext )
|
||||
{
|
||||
if ( ltext.Scroll(16) ) master.MenuSound("menu/demoscroll");
|
||||
break;
|
||||
}
|
||||
if ( sel[section] < lists[section].items.Size()-1 )
|
||||
{
|
||||
lists[section].selected = ++sel[section];
|
||||
master.MenuSound("menu/demoscroll");
|
||||
KBScroll();
|
||||
}
|
||||
break;
|
||||
case MK_UP:
|
||||
if ( clore && ltext )
|
||||
{
|
||||
if ( ltext.Scroll(-16) ) master.MenuSound("menu/demoscroll");
|
||||
break;
|
||||
}
|
||||
if ( sel[section] > 0 )
|
||||
{
|
||||
lists[section].selected = --sel[section];
|
||||
master.MenuSound("menu/demoscroll");
|
||||
KBScroll();
|
||||
}
|
||||
break;
|
||||
case MK_ENTER:
|
||||
if ( clore ) break;
|
||||
if ( active ) active.bActive = false;
|
||||
active = DemolitionistMenuLoreItem(lists[section].items[sel[section]]);
|
||||
active.bActive = true;
|
||||
clore = active.ent;
|
||||
if ( !ltext ) ltext = new("DemolitionistMenuTextBox").Init(master,StringTable.Localize(clore.text),lwidth+((maxofs[section]>0)?8:0));
|
||||
else ltext.Reinit(StringTable.Localize(clore.text),lwidth+((maxofs[section]>0)?8:0));
|
||||
ltext.img = clore.img;
|
||||
master.MenuSound("menu/demosel");
|
||||
active.MarkRead();
|
||||
break;
|
||||
case MK_BACK:
|
||||
if ( !clore ) break;
|
||||
if ( active ) active.bActive = false;
|
||||
clore = null;
|
||||
master.MenuSound("menu/democlose");
|
||||
break;
|
||||
}
|
||||
}
|
||||
override void Drawer()
|
||||
{
|
||||
double xx = 0;
|
||||
double yy = 15;
|
||||
String str = sname[section];
|
||||
master.DrawVSeparator(lwidth,14,master.ws.y-28);
|
||||
master.DrawHSeparator(0,28,lwidth);
|
||||
Screen.DrawText(smallfont,Font.CR_FIRE,master.origin.x+(lwidth-smallfont.StringWidth(str))/2,master.origin.y+yy,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
bool hasprev = false;
|
||||
bool hasunreadprev = false;
|
||||
for ( int i=0; i<section; i++ )
|
||||
{
|
||||
if ( lists[i].items.Size() <= 0 )
|
||||
continue;
|
||||
hasprev = true;
|
||||
for ( int j=0; j<lists[i].items.Size(); j++ )
|
||||
{
|
||||
if ( DemolitionistMenuLoreItem(lists[i].items[j]).ent.read ) continue;
|
||||
hasunreadprev = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool hasnext = false;
|
||||
bool hasunreadnext = false;
|
||||
for ( int i=section+1; i<4; i++ )
|
||||
{
|
||||
if ( lists[i].items.Size() <= 0 )
|
||||
continue;
|
||||
hasnext = true;
|
||||
for ( int j=0; j<lists[i].items.Size(); j++ )
|
||||
{
|
||||
if ( DemolitionistMenuLoreItem(lists[i].items[j]).ent.read ) continue;
|
||||
hasunreadnext = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( hasprev )
|
||||
Screen.DrawText(smallfont,Font.CR_WHITE,master.origin.x+3,master.origin.y+yy,"<",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
if ( hasunreadprev )
|
||||
Screen.DrawText(smallfont,Font.CR_GOLD,master.origin.x+9,master.origin.y+yy,"‼",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
if ( hasnext )
|
||||
Screen.DrawText(smallfont,Font.CR_WHITE,master.origin.x+lwidth-9,master.origin.y+yy,">",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
if ( hasunreadnext )
|
||||
Screen.DrawText(smallfont,Font.CR_GOLD,master.origin.x+lwidth-15,master.origin.y+yy,"‼",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
xx = 3;
|
||||
yy = 32;
|
||||
int cliptop = int((master.origin.y+32)*master.hs);
|
||||
int clipbottom = int((master.origin.y+master.ws.y-18)*master.hs);
|
||||
int clipleft = int((master.origin.x+3)*master.hs);
|
||||
int clipright = int((master.origin.x+lwidth-3)*master.hs);
|
||||
lists[section].Drawer((xx,yy-smofs[section]),cliptop,clipbottom,clipleft,clipright);
|
||||
if ( maxofs[section] > 0 )
|
||||
{
|
||||
xx = lwidth;
|
||||
master.DrawVSeparator(xx+8,14,master.ws.y-28);
|
||||
xx += 2;
|
||||
yy = floor(smofs[section]*((master.ws.y-39)/maxofs[section]))+14;
|
||||
Screen.DrawText(smallfont,Font.CR_FIRE,master.origin.x+xx,master.origin.y+yy,"▮",DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
|
||||
}
|
||||
if ( clore && ltext ) ltext.Drawer();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ Class SWWMTradeHistory : Thinker
|
|||
enum ELoreTab
|
||||
{
|
||||
LORE_ITEM,
|
||||
LORE_ENEMY,
|
||||
LORE_PEOPLE,
|
||||
LORE_LORE // lol
|
||||
};
|
||||
|
|
@ -351,6 +352,7 @@ enum ELoreTab
|
|||
Class SWWMLore
|
||||
{
|
||||
String tag, text, assoc;
|
||||
TextureID img;
|
||||
int tab;
|
||||
bool read;
|
||||
}
|
||||
|
|
@ -524,6 +526,7 @@ Class SWWMLoreLibrary : Thinker
|
|||
if ( ttab ~== "People" ) e.tab = LORE_PEOPLE;
|
||||
else if ( ttab ~== "Lore" ) e.tab = LORE_LORE;
|
||||
else if ( ttab ~== "Item" ) e.tab = LORE_ITEM;
|
||||
else if ( ttab ~== "Enemy" ) e.tab = LORE_ENEMY;
|
||||
else
|
||||
{
|
||||
Console.Printf("Entry \"%s\" has an incorrect tab setting of \"%s\".",ref,ttab);
|
||||
|
|
@ -537,6 +540,8 @@ Class SWWMLoreLibrary : Thinker
|
|||
}
|
||||
e.assoc = "$"..assoc;
|
||||
e.read = false;
|
||||
// image for certain entries
|
||||
e.img = TexMan.CheckForTexture("graphics/KBase/PFP_"..ref..".png",TexMan.Type_Any);
|
||||
// "new lore" message
|
||||
if ( (level.maptime > 0) && (gametic > lastaddtic) && (myplayer == players[consoleplayer]) && (!menuactive || (menuactive == Menu.OnNoPause)) && (myplayer.mo is 'Demolitionist') )
|
||||
Console.Printf(StringTable.Localize("$SWWM_NEWLORE"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue