/**
* @class Scene
* @brief Represents an on-screen view into the world
* @author Samuel Kaufman
* @date 2002
*/
// vim:ts=2 sw=2
#include "uop.h"
#include <SDL/SDL.h>
#include <sstream>
#include "interfacegumps.h"
#include "gumps.h"
#include "interface.h"
#include "interfacehandler.h"
#include "cliloc.h"
#include "texthandler.h"
#include "world.h"
extern SDL_Surface *screen;
extern Gumps *gumps;
extern Interface *intrface;
extern InterfaceHandler *interfaceHandler;
extern vector<Cliloc *>intlocs;
extern vector<Cliloc *>clilocs;
extern Cliloc *profession;
extern TextHandler *textHandler;
extern World *world;
InterfaceGump::InterfaceGump()
{
x=y=width=height=0;
fontcolor=0;
partial=0;
fontNumber=1;
emboss=engrave=false;
}
InterfaceGump::~InterfaceGump()
{
}
void InterfaceGump::add(InterfaceGump *gump)
{
gump->partial=partial;
gump->fontcolor=fontcolor;
children.push_back(gump);
}
InterfaceGump *InterfaceGump::getLast()
{
return children.back();
}
void InterfaceGump::draw()
{
}
void InterfaceGump::move(int x,int y,int w,int h)
{
this->x=x; //default movement makes children same size as parent...
this->y=y;
width=w;
height=h;
}
bool InterfaceGump::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
return false;
}
bool InterfaceGump::mouseUp(Uint8 button,Uint16 x,Uint16 y)
{
return false;
}
bool InterfaceGump::mouseDoubleClick(Uint8 button,Uint16 x,Uint16 y)
{
return false;
}
InterfaceGump *InterfaceGump::mouseEnter(Uint16 x,Uint16 y)
{
return NULL;
}
void InterfaceGump::mouseExit()
{
}
bool InterfaceGump::mouseMove(Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
return true;
return false;
}
GumpMain::GumpMain(string &name)
{
sx="0"; sy="0";
sw="R"; sh="B";
gumpName=name;
close=NULL;
hasRect=false;
}
GumpMain::~GumpMain()
{
}
void GumpMain::move(int x,int y,int w,int h)
{
list<InterfaceGump *>::iterator i;
this->x=x+myEval(this->sx,w,h);
this->y=y+myEval(this->sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
if (!width) width=w;
if (!height) height=h;
for (i=children.begin();i!=children.end();i++)
(*i)->move(this->x,this->y,width,height);
}
void GumpMain::draw()
{
list<InterfaceGump *>::iterator i;
for (i=children.begin();i!=children.end();i++)
(*i)->draw();
}
bool GumpMain::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
bool done=false;
Uint16 tx=x-this->x;
Uint16 ty=y-this->y;
if (tx<width && ty<height)
{
list<InterfaceGump *>::reverse_iterator i;
for (i=children.rbegin();(i!=children.rend()) && !done;i++)
done=(*i)->mouseDown(button,x,y);
}
return done;
}
bool GumpMain::mouseUp(Uint8 button,Uint16 x,Uint16 y)
{
bool done=false;
Uint16 tx=x-this->x;
Uint16 ty=y-this->y;
if (tx<width && ty<height)
{
list<InterfaceGump *>::reverse_iterator i;
for (i=children.rbegin();(i!=children.rend()) && !done;i++)
done=(*i)->mouseUp(button,x,y);
}
return done;
}
InterfaceGump *GumpMain::mouseEnter(Uint16 x,Uint16 y)
{
InterfaceGump *done=NULL;
Uint16 tx=x-this->x;
Uint16 ty=y-this->y;
if (tx<width && ty<height)
{
list<InterfaceGump *>::reverse_iterator i;
for (i=children.rbegin();(i!=children.rend()) && !done;i++)
done=(*i)->mouseEnter(x,y);
}
return done;
}
GumpRect::GumpRect(string &args)
{
istringstream s(args);
x=y=width=height=0;
s>>sx>>sy>>sw>>sh;
x=myEval(sx,0,0);
y=myEval(sy,0,0);
width=myEval(sw,0,0);
height=myEval(sh,0,0);
}
GumpRect::~GumpRect()
{
}
GumpBackground::GumpBackground(string &args)
{
istringstream s(args);
s>>gumpID>>sx>>sy>>flag;
}
void GumpBackground::move(int x,int y,int w,int h)
{
if (!flag)
{
x+=myEval(this->sx,w,h);
y+=myEval(this->sy,w,h);
}
this->x=x;
this->y=y;
this->width=w;
this->height=h;
gump.load(gumpID,this->width,this->height,flag);
}
void GumpBackground::draw()
{
gump.blit(x,y,HuePartial,partial);
}
GumpBackground::~GumpBackground(){
}
GumpInterface::GumpInterface(string &args)
{
istringstream s(args);
string name;
s>>id>>name>>sx>>sy>>sw>>sh;
children.push_back(intrface->getGump(name));
}
GumpInterface::~GumpInterface(){
}
void GumpInterface::move(int x,int y,int w,int h)
{
list<InterfaceGump *>::iterator i;
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
for (i=children.begin();i!=children.end();i++)
{
if(!*i)
continue;
(*i)->move(this->x,this->y,width,height);
if ((*i)->x<this->x) this->x=(*i)->x;
if ((*i)->y<this->y) this->y=(*i)->y;
if ((*i)->x+(*i)->width>this->x+width) width=(*i)->x+(*i)->width-this->x;
if ((*i)->y+(*i)->height>this->y+height) height=(*i)->y+(*i)->height-this->y;
}
}
void GumpInterface::draw()
{
list<InterfaceGump *>::iterator i;
for (i=children.begin();i!=children.end();i++)
if(*i)
(*i)->draw();
}
bool GumpInterface::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
bool done=false;
Uint16 tx=x-this->x;
Uint16 ty=y-this->y;
if (tx<width && ty<height)
{
list<InterfaceGump *>::reverse_iterator i;
for (i=children.rbegin();(i!=children.rend()) && !done;i++)
done=(*i)->mouseDown(button,x,y);
}
return done;
}
GumpSizableBackground::GumpSizableBackground(string &args)
{
istringstream s(args);
s>>sx>>sy>>sw>>sh>>g[0]>>g[1]>>g[2]>>g[3]>>g[4]>>g[5]>>g[6]>>g[7]>>g[8]>>flag;
}
GumpSizableBackground::~GumpSizableBackground(){
}
void GumpSizableBackground::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
gump.load(g,width,height);
}
void GumpSizableBackground::draw()
{
gump.blit(x,y,HuePartial,partial);
}
GumpButton::GumpButton(string &args)
{
istringstream s(args);
s>>ID>>sx>>sy>>gumpID>>downID>>overID>>flag1>>flag2;
GumpIndex &idx=gumps->getIndex(gumpID);
height=idx.height;
width=idx.width;
normal.load(gumpID);
over.load(overID);
down.load(downID);
gump=&normal;
mOver=mDown=false;
}
GumpButton::~GumpButton(){
}
void GumpButton::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
}
void GumpButton::draw()
{
gump->blit(x,y,HuePartial,partial);
}
bool GumpButton::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=true;
gump=&down;
return true;
}
return false;
}
bool GumpButton::mouseUp(Uint8 button,Uint16 x,Uint16 y)
{
if (!mDown) return false;
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=false;
gump=&over;
interfaceHandler->buttonClicked(ID);
return true;
}
return false;
}
InterfaceGump *GumpButton::mouseEnter(Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mOver=true;
gump=&over;
return this;
}
return NULL;
}
void GumpButton::mouseExit()
{
mOver=mDown=false;
gump=&normal;
}
GumpLayoutButton::GumpLayoutButton(string &args)
{
istringstream s(args);
string sgump,sdown,sover;
s>>ID>>sx>>sy>>sw>>sh>>sgump>>sdown>>sover>>text;
if (text[0]>='0' && text[0]<='9')
{
istringstream s(text);
Uint32 clID;
Uint16 clType,clGroup;
s>>clID;
clType=clID/1000000;
clGroup=(clID/1000)%1000;
clID%=1000;
if (clType==3)
text=intlocs[clGroup]->getString(clID);
else
text=clilocs[clGroup]->getString(clID);
}
else
{
string::iterator i;
for (i=text.begin();i!=text.end();i++)
if ((*i)=='_') (*i)=' ';
}
interfaceHandler->primeText(text);
normal=intrface->getGump(sgump);
down=intrface->getGump(sdown);
over=intrface->getGump(sover);
gump=normal;
mOver=mDown=false;
}
GumpLayoutButton::~GumpLayoutButton(){
}
void GumpLayoutButton::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
normal->move(this->x,this->y,width,height);
down->move(this->x,this->y,width,height);
over->move(this->x,this->y,width,height);
}
void GumpLayoutButton::draw()
{
gump->draw();
}
bool GumpLayoutButton::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=true;
gump=down;
return true;
}
return false;
}
bool GumpLayoutButton::mouseUp(Uint8 button,Uint16 x,Uint16 y)
{
if (!mDown) return false;
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=false;
gump=over;
interfaceHandler->buttonClicked(ID);
return true;
}
return false;
}
InterfaceGump *GumpLayoutButton::mouseEnter(Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mOver=true;
gump=over;
return this;
}
return NULL;
}
void GumpLayoutButton::mouseExit()
{
mOver=mDown=false;
gump=normal;
}
GumpDecoration::GumpDecoration(string &args)
{
string tgump,temp;
istringstream s(args);
flag=0;
s>>ID>>sx>>sy>>tgump>>flag;
if (flag==1)
{
temp=sx;
sx=sy;
sy=tgump;
tgump=temp;
}
istringstream ss(tgump);
ss>>gumpID;
GumpIndex &idx=gumps->getIndex(gumpID);
height=idx.height;
width=idx.width;
gump.load(gumpID);
}
GumpDecoration::~GumpDecoration(){
}
void GumpDecoration::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
}
void GumpDecoration::draw()
{
gump.blit(x,y,HuePartial,partial);
}
GumpText::GumpText(string &args)
{
istringstream s(args);
string sunk;
s>>sx>>sy>>sw>>sh>>sunk>>text;
if (sunk[0]>='0' && sunk[0]<='9') //alignment present
{
istringstream ss(sunk);
ss>>unk;
}
else
{
text=sunk;
unk=0;
}
if (text[0]>='0' && text[0]<='9')
{
istringstream s(text);
Uint32 clID;
Uint16 clType,clGroup;
s>>clID;
clType=clID/1000000;
clGroup=(clID/1000)%1000;
clID%=1000;
if (clType==3)
text=intlocs[clGroup]->getString(clID);
else
text=clilocs[clGroup]->getString(clID);
}
else
{
string::iterator i;
for (i=text.begin();i!=text.end();i++)
if ((*i)=='_') (*i)=' ';
}
}
GumpText::~GumpText(){
}
void GumpText::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
}
void GumpText::draw()
{
int centerx;
int centery=y;
bool done=false;
Uint16 start,end;
start=0;
string str=text;
while (!done)
{
centerx=x;
done=true;
end=str.length()-start;
string sub;
latin2unicode(str.substr(start,end), sub);
if (textHandler->unicodeWidth(sub,fontNumber)>width)
{
done=false;
while (textHandler->unicodeWidth(sub,fontNumber)>width)
{
end--;
latin2unicode(str.substr(start,end), sub);
}
Uint16 oldEnd=end;
while (str[end+start]!=' ' && end>0) end--;
if (!end) end=oldEnd;
}
latin2unicode(str.substr(start,end), sub);
if (unk==64)
{
int w=textHandler->unicodeWidth(sub,fontNumber);
centerx+=((width-w)-1)>>1;
}
textHandler->drawUnicodeString(sub,fontNumber,centerx,centery,fontcolor);
centery+=textHandler->unicodeHeight(fontNumber)<<1;
if (!done)
{
if (str[end+start]!=' ')
start+=end;
else
start+=end+1;
}
}
}
GumpInterfaceButton::GumpInterfaceButton(string &args)
{
string sgump,sdown,sover;
istringstream s(args);
s>>ID>>sx>>sy>>sw>>sh>>sgump>>sdown>>sover>>text;
if (text.length()>0)
{
if (text[0]>='0' && text[0]<='9')
{
istringstream s(text);
Uint32 clID;
Uint16 clType,clGroup;
s>>clID;
clType=clID/1000000;
clGroup=(clID/1000)%1000;
clID%=1000;
if (clType==3)
text=intlocs[clGroup]->getString(clID);
else
text=clilocs[clGroup]->getString(clID);
}
}
else
{
int id;
id=interfaceHandler->getNextCharacter();
text=interfaceHandler->getCharacter(id);
ID*=10;
ID+=id;
}
interfaceHandler->primeText(text);
normal=intrface->getGump(sgump);
down=intrface->getGump(sdown);
over=intrface->getGump(sover);
gump=normal;
mOver=mDown=false;
}
GumpInterfaceButton::~GumpInterfaceButton(){
}
void GumpInterfaceButton::move(int x,int y,int w,int h)
{
this->x=x+myEval(sx,w,h);
this->y=y+myEval(sy,w,h);
width=myEval(sw,w,h);
height=myEval(sh,w,h);
normal->move(this->x,this->y,width,height);
down->move(this->x,this->y,width,height);
over->move(this->x,this->y,width,height);
}
void GumpInterfaceButton::draw()
{
gump->draw();
}
bool GumpInterfaceButton::mouseDown(Uint8 button,Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=true;
gump=down;
return true;
}
return false;
}
bool GumpInterfaceButton::mouseUp(Uint8 button,Uint16 x,Uint16 y)
{
if (!mDown) return false;
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mDown=false;
gump=over;
interfaceHandler->buttonClicked(ID);
return true;
}
return false;
}
InterfaceGump *GumpInterfaceButton::mouseEnter(Uint16 x,Uint16 y)
{
x-=this->x;
y-=this->y;
if (x<width && y<height)
{
mOver=true;
gump=over;
return this;
}
return NULL;
}
void GumpInterfaceButton::mouseExit()
{
mOver=mDown=false;
gump=normal;
}
GumpInterfaceRadioButton::GumpInterfaceRadioButton(string &args)
{
string g,gover,gdown,g2,g2over,g2down;
istringstream s(args);
s>>ID>>ID2>>Choice>>sx>>sy>>sw>>sh>>g>>gdown>>gover>>
g2>>g2down>>g2over>>text>>text2;