/*
* Variables for dialog boxes / options.
- */
+ */
- static char dialogBoxText[512];
- static char *dialogOptText[4];
- static float dialogOptLoc[4][3];
+ static char dialogBoxText[512];
+ static char *dialogOptText[4];
++static float merchAOptLoc[2][3];
+ static float dialogOptLoc[4][3];
static unsigned char dialogOptCount = 0;
- static bool typeOutDone = true;
+ static bool typeOutDone = true;
-static int dialogPassiveTime = 0;
+
+ /*
+ * Menu-related objects
+ */
- extern Menu* currentMenu;
+ extern Menu *currentMenu;
extern Menu pauseMenu;
+ /**
+ * The sound made when displaying characters with dialogBox or importantText.
+ */
static Mix_Chunk *dialogClick;
}
void Menu::gotoChild(){
- if(child == NULL){
+ if(!child)
currentMenu = NULL;
- }else{
+ else
currentMenu = child;
- }
}
+ static vec2 premouse={0,0};
+
namespace ui {
- /*
- * Mouse coordinates.
- */
+ /**
+ * The current position of the mouse.
+ */
vec2 mouse;
- static vec2 premouse={0,0};
- /*
- * Variety of keydown bools
- */
- bool edown;
-
- /*
- * Debugging flags.
- */
+ /**
+ * If true, debug information will be drawn to the screen.
+ */
+
+ bool debug = false;
+
+ /**
+ * If true, lines should be drawn to the player when the debug menu is open.
+ */
- bool debug=false;
bool posFlag=false;
+
+ /**
+ * If true, the player will be able to move when the current dialog box is
+ * displayed.
+ */
+
bool dialogPassive = false;
+ bool dialogMerchant = false;
++ std::vector<BuySell> *minv;
+ int dialogPassiveTime = 0;
-
- /*
- * Dialog stuff that needs to be 'public'.
- */
+ /**
+ * When set to true the dialog box will attempt to display.
+ */
bool dialogBoxExists = false;
+
+ /**
+ * When set to true the text will display as 'important' text.
+ */
+
bool dialogImportant = false;
+
+ /**
+ * Contains the last chosen dialog option.
+ */
+
unsigned char dialogOptChosen = 0;
+ /**
+ * Determines how many characters can be displayed in a dialog box before
+ * a new line is required.
+ */
+
unsigned int textWrapLimit = 110;
- /*
- * Current font size. Changing this WILL NOT change the font size, see setFontSize() for
- * actual font size changing.
- */
+ /**
+ * The current font size.
+ *
+ * DO NOT change this directly, use setFontSize() instead.
+ */
unsigned int fontSize;
#ifdef DEBUG
DEBUG_printf("Using font %s\n",ttf);
#endif // DEBUG
+
}
- /*
- * Sets a new font size (default: 12).
- */
+ /**
+ * Sets a new font size and renders the necessary characters (default font
+ * size: 16; 24 for importantText).
+ */
void setFontSize(unsigned int size){
+ mtx.lock();
unsigned int i,j;
- char *buf;
- fontSize=size;
-
- FT_Set_Pixel_Sizes(ftf,0,fontSize);
+ std::unique_ptr<uint8_t[]> rgbaBuf;
+ size_t rgbaBufSize = 0;
- /*
- * Pre-render 'all' the characters.
- */
+ FT_Set_Pixel_Sizes(ftf,0,(fontSize = size));
- glDeleteTextures(93,ftex); // delete[] any already-rendered textures
- glGenTextures(93,ftex); // Generate new texture name/locations?
+ // delete old characters, make space for new ones
+ for(i=0; i < FT_CHAR_COUNT; i++){
+ glDeleteTextures(1, &ftmap[i].tex);
+ glGenTextures(1, &ftmap[i].tex);
+ }
+ // Load all characters we expect to use
for(i=33;i<126;i++){
- /*
- * Load the character from the font family file.
- */
- //uiLoop ? std::cout << "Loop while render\n" : std::cout << "No loop while render\n";
+ // Load the bitmap for the current character.
if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){
std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl;
abort();
}
/*
- * Transfer the character's bitmap (?) to a texture for rendering.
- */
+ * Set up the OpenGL texture thing.
+ */
- glBindTexture(GL_TEXTURE_2D,ftex[i-33]);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S ,GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T ,GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER ,GL_LINEAR );
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER ,GL_LINEAR );
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glBindTexture(GL_TEXTURE_2D, ftmap[i-33].tex);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR );
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR );
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/*
- * The just-created texture will render red-on-black if we don't do anything to it, so
- * here we create a buffer 4 times the size and transform the texture into an RGBA array,
- * making it white-on-black.
- */
-
- buf = new char[ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4];
+ * Convert the bitmap font given to us from FreeType into an RGBA
+ * format, for ease of drawing.
+ */
+
+ rgbaBuf.reset(new uint8_t [(rgbaBufSize = ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4)]);
+ rgbaBufSize /= 4;
- for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){
- buf[j*4 ]=255;//fontColor[0];
- buf[j*4+1]=255;//fontColor[1];
- buf[j*4+2]=255;//fontColor[2];
- buf[j*4+3]=ftf->glyph->bitmap.buffer[j] ? 255 : 0;
- //buf[j*4+3]=ftf->glyph->bitmap.buffer[j];
+ // populate the buffer
+ for(j=0; j < rgbaBufSize; j++){
+ rgbaBuf[j * 4 ] =
+ rgbaBuf[j * 4 + 1] =
+ rgbaBuf[j * 4 + 2] = 255;
+ rgbaBuf[j * 4 + 3] = ftf->glyph->bitmap.buffer[j] ? 255 : 0;
}
- ftexwh[i-33].x=ftf->glyph->bitmap.width;
- ftexwh[i-33].y=ftf->glyph->bitmap.rows;
- ftexbl[i-33].x=ftf->glyph->bitmap_left;
- ftexbl[i-33].y=ftf->glyph->bitmap_top;
- ftexad[i-33].x=ftf->glyph->advance.x>>6;
- ftexad[i-33].y=ftf->glyph->advance.y>>6;
+ // save important character information
+ ftmap[i-33].wh = { (int)ftf->glyph->bitmap.width, (int)ftf->glyph->bitmap.rows };
+ ftmap[i-33].bl = { ftf->glyph->bitmap_left, ftf->glyph->bitmap_top };
+ ftmap[i-33].ad = { ftf->glyph->advance.x >> 6, ftf->glyph->advance.y >> 6 };
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
+ // do the thing
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get());
- delete[] buf; //free(buf);
+ rgbaBuf.release();
}
+ mtx.unlock();
}
- /*
- * Set a color for font rendering (default: white).
- */
+ /**
+ * Set a color for font rendering (default: white).
+ */
void setFontColor(unsigned char r,unsigned char g,unsigned char b){
fontColor[0]=r;
float putText(const float x,const float y,const char *str,...){
va_list args;
- char *buf;
- float width;
-
- /*
- * Create a wimpy buffer.
- */
-
- buf = new char[512]; //(char *)calloc(128,sizeof(char));
- memset(buf,0,512*sizeof(char));
-
- /*
- * Handle the formatted string, printing it to the buffer.
- */
+ std::unique_ptr<char[]> buf (new char[512]);
- va_start(args,str);
- vsnprintf(buf,512,str,args);
+ // create the formatted string
+ va_start(args, str);
+ vsnprintf(buf.get(), 512, str, args);
va_end(args);
- /*
- * Draw the string, free resources, return the width of the string.
- */
-
- width=putString(x,y,buf);
- delete[] buf; //free(buf);
-
- return width;
+ return putString(x, y, buf.get());
}
+
+ /**
+ * Prints a character dialog box.
+ *
+ * This function sets up the variables necessary to draw a dialog box. If
+ * `opt` contains a valid string, options will be printed with the dialog
+ * box. If the box is passive, the player will be allowed to move while it
+ * is being displayed.
+ */
+
void dialogBox(const char *name,const char *opt,bool passive,const char *text,...){
++ textWrapLimit = 110;
va_list dialogArgs;
- unsigned int len;
- char *sopt,*soptbuf;
+ size_t len;
dialogPassive = passive;
dialogOptCount--;
};
- dialogOptCount = 0;
dialogOptChosen = 0;
- memset(&dialogOptLoc,0,sizeof(float)*12);
+ memset(&dialogOptLoc, 0, sizeof(float) * 12);
++ //char *sopt = (char*)malloc(255);
++ //dialogOptCount = 4;
- if(opt != NULL){
-
- soptbuf = new char[strlen(opt)+1];
- strcpy(soptbuf,opt);
-
- sopt=strtok(soptbuf,":");
- while(sopt != NULL){
- dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt));
- strcpy(dialogOptText[dialogOptCount++],sopt);
- sopt=strtok(NULL,":");
+ // handle options if desired
+ if(opt){
- std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]);
- char *sopt = strtok(soptbuf.get(), ":");
++ //std::vector<char*> soptbuf (new char[strlen(opt) + 1]);
++ //std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]);
++ char soptbuf[255];
++ strcpy(soptbuf, opt);
++ char *sopt = strtok(soptbuf, ":");
+
+ // cycle through options
+ while(sopt){
++ printf("%s",sopt);
+ strcpy( (dialogOptText[dialogOptCount++] = new char[strlen(sopt) + 1]), sopt);
+ sopt = strtok(NULL,":");
}
-
- delete[] soptbuf;
-
}
- /*
- * Tell draw() that the box is ready.
- */
-
+ // allow box to be displayed
dialogBoxExists = true;
dialogImportant = false;
- if(ret)
- ret[0] = '\0';
+ // kill the string created by typeOut if it contains something
+ if(typeOutStr)
+ *typeOutStr = '\0';
}
- void merchantBox(const char *name,const char *opt,bool passive,const char *text,...){
++
++ void merchantBox(const char *name,std::vector<BuySell> *bsinv,const char *opt,bool passive,const char *text,...){
+ std::cout << "Buying and selling on the bi-weekly!" << std::endl;
+ va_list dialogArgs;
- unsigned int len;
- char *sopt,*soptbuf;
++ size_t len;
+
++ minv = bsinv;
+ dialogPassive = passive;
+
- /*
- * Set up the text buffer.
- */
++ // clear the buffer
++ memset(dialogBoxText, '\0', 512);
+
- memset(dialogBoxText,0,512);
-
- /*
- * Get the text ready for rendering.
- */
-
- len=strlen(name);
- strcpy(dialogBoxText ,name);
- strcpy(dialogBoxText+len,": ");
- len+=2;
++ // create the string
++ strcpy(dialogBoxText, name);
++ strcat(dialogBoxText, ": ");
+
++ len=strlen(dialogBoxText);
+ va_start(dialogArgs,text);
- vsnprintf(dialogBoxText+len,512-len,text,dialogArgs);
++ vsnprintf(dialogBoxText + len, 512 - len, text, dialogArgs);
+ va_end(dialogArgs);
+
- /*
- * Set up option text.
- */
-
++ // free old option text
+ while(dialogOptCount){
+ if(dialogOptText[dialogOptCount]){
- delete[] dialogOptText[dialogOptCount]; //free(dialogOptText[dialogOptCount]);
++ delete[] dialogOptText[dialogOptCount];
+ dialogOptText[dialogOptCount] = NULL;
+ }
++
+ dialogOptCount--;
+ };
+
- dialogOptCount = 0;
+ dialogOptChosen = 0;
- memset(&dialogOptLoc,0,sizeof(float)*12);
++ memset(&dialogOptLoc, 0, sizeof(float) * 12);
+
- if(opt != NULL){
-
- soptbuf = new char[strlen(opt)+1];
- strcpy(soptbuf,opt);
-
- sopt=strtok(soptbuf,":");
- while(sopt != NULL){
- dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt));
- strcpy(dialogOptText[dialogOptCount++],sopt);
- sopt=strtok(NULL,":");
++ // handle options if desired
++ if(opt){
++ //std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]);
++ char soptbuf[255];
++ strcpy(soptbuf, opt);
++ char *sopt = strtok(soptbuf, ":");
++
++ // cycle through options
++ while(sopt){
++ strcpy( (dialogOptText[dialogOptCount++] = new char[strlen(sopt) + 1]), sopt);
++ sopt = strtok(NULL,":");
+ }
-
- delete[] soptbuf;
-
+ }
+
- /*
- * Tell draw() that the box is ready.
- */
-
++ // allow box to be displayed
+ dialogBoxExists = true;
+ dialogImportant = false;
+ dialogMerchant = true;
++ textWrapLimit = 50;
+
- if(ret)
- ret[0] = '\0';
++ // kill the string created by typeOut if it contains something
++ if(typeOutStr)
++ *typeOutStr = '\0';
++ }
++
++ void merchantBox(){
++ textWrapLimit = 50;
++ dialogMerchant = true;
+ }
+
+ /**
+ * Wait for a dialog box to be dismissed.
+ */
+
void waitForDialog(void){
do{
mainLoop();
float x,y,tmp;
char *rtext;
+ // handle dialog box / important text
if(dialogBoxExists){
- rtext=typeOut(dialogBoxText);
+ rtext = typeOut(dialogBoxText);
if(dialogImportant){
- setFontColor(255,255,255);
- if(dialogPassive){
- dialogPassiveTime -= deltaTime;
- if(dialogPassiveTime < 0){
- dialogPassive = false;
- dialogImportant = false;
- dialogBoxExists = false;
- }
+ setFontColor(255, 255, 255);
+
+ // handle timeout
+ if(dialogPassive && (dialogPassiveTime -= deltaTime) <= 0){
+ dialogPassive = false;
+ dialogImportant = false;
+ dialogBoxExists = false;
}
+
+ // draw text
if(fadeIntensity == 255 || dialogPassive){
setFontSize(24);
- putStringCentered(offset.x,offset.y,rtext);
+ putStringCentered(offset.x, offset.y, rtext);
setFontSize(16);
}
- }else{ // normal dialog box
- x = offset.x - SCREEN_WIDTH / 2 + HLINE * 8;
- y = (offset.y + SCREEN_HEIGHT / 2) - HLINE * 8;
+ }else if(dialogMerchant){
- /*static std::string merchOpt[3] = {"Accept",
- "Cancel"};*/
-
+ x=offset.x-SCREEN_WIDTH/6;
+ y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8;
+
+
+ glColor3ub(255,255,255);
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(x-1 ,y+1);
+ glVertex2f(x+1+(SCREEN_WIDTH/3),y+1);
+ glVertex2f(x+1+(SCREEN_WIDTH/3),y-1-SCREEN_HEIGHT*.6);
+ glVertex2f(x-1,y-1-SCREEN_HEIGHT*.6);
+ glVertex2f(x,y+1);
+ glEnd();
- for(i=0;i<dialogOptCount;i++){
- dialogOptLoc[i][1] = (y-SCREEN_HEIGHT*.55) - i*fontSize;
- setFontColor(255,255,255);
- tmp = putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]);
+ glColor3ub(0,0,0);
+ glRectf(x,y,x+SCREEN_WIDTH/3,y-SCREEN_HEIGHT*.6);
+
- //merchOptLoc[i][1] = y - SCREEN_HEIGHT / 4 + (fontSize + HLINE) * (i + 1);
- if(mouse.x > dialogOptLoc[i][0] &&
- mouse.x < dialogOptLoc[i][2] &&
- mouse.y > dialogOptLoc[i][1] &&
- mouse.y < dialogOptLoc[i][1] + fontSize){ // fontSize
- setFontColor(255,255,0);
- putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]);
++ // draw typeOut'd text
++ putString(x + HLINE, y - fontSize - HLINE, (rtext = typeOut(dialogBoxText)));
++ merchAOptLoc[0][0] = offset.x - (SCREEN_WIDTH / 5.5);
++ merchAOptLoc[0][1] = offset.x + (SCREEN_WIDTH / 5.5);
++ merchAOptLoc[1][0] = offset.y + (SCREEN_HEIGHT *.25);
++ merchAOptLoc[1][1] = offset.y + (SCREEN_HEIGHT *.25);
++ merchAOptLoc[2][0] = offset.x - (SCREEN_WIDTH / 5.5) - 16;
++ merchAOptLoc[2][1] = offset.x + (SCREEN_WIDTH / 5.5) + 16;
++
++ glColor3ub(255,255,255);
++ glBegin(GL_TRIANGLES);
++ glVertex2f(merchAOptLoc[2][0],merchAOptLoc[1][0]);
++ glVertex2f(merchAOptLoc[0][0],merchAOptLoc[1][0]-8);
++ glVertex2f(merchAOptLoc[0][0],merchAOptLoc[1][0]+8);
++ glEnd();
++
++ // draw / handle dialog options if they exist
++ for(i = 0; i < dialogOptCount; i++){
++ setFontColor(255, 255, 255);
++
++ // draw option
++ tmp = putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]);
++
++ // get coordinate information on option
+ dialogOptLoc[i][2] = offset.x + tmp;
+ dialogOptLoc[i][0] = offset.x - tmp;
- setFontColor(255,255,255);
- }else{
++ dialogOptLoc[i][1] = y - SCREEN_HEIGHT / 2 - (fontSize + HLINE) * (i + 1);
++
++ // make text yellow if the mouse hovers over the text
++ if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] &&
++ mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){
++ setFontColor(255, 255, 0);
++ putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]);
+ }
+ }
-
-
- glColor3ub(255,255,255);
++
++ setFontColor(255, 255, 255);
++ }else{ //normal dialog box
+
+ x=offset.x-SCREEN_WIDTH/2+HLINE*8;
+ y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8;
++
+ // draw white border
+ glColor3ub(255, 255, 255);
glBegin(GL_LINE_STRIP);
- glVertex2f(x-1 ,y+1);
- glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y+1);
- glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y-1-SCREEN_HEIGHT/4);
- glVertex2f(x-1 ,y-1-SCREEN_HEIGHT/4);
- glVertex2f(x ,y+1);
+ glVertex2f(x - 1 , y + 1 );
+ glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y + 1 );
+ glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y - 1 - SCREEN_HEIGHT / 4 );
+ glVertex2f(x - 1 , y - 1 - SCREEN_HEIGHT / 4 );
+ glVertex2f(x , y + 1 );
glEnd();
- glColor3ub(0,0,0);
- glRectf(x,y,x+SCREEN_WIDTH-HLINE*16,y-SCREEN_HEIGHT/4);
-
- rtext=typeOut(dialogBoxText);
+ // draw black box
+ glColor3ub(0, 0, 0);
+ glRectf(x, y, x + SCREEN_WIDTH - HLINE * 16, y - SCREEN_HEIGHT / 4);
- putString(x+HLINE,y-fontSize-HLINE,rtext);
+ // draw typeOut'd text
+ putString(x + HLINE, y - fontSize - HLINE, (rtext = typeOut(dialogBoxText)));
- for(i=0;i<dialogOptCount;i++){
- setFontColor(255,255,255);
- tmp = putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]);
+ // draw / handle dialog options if they exist
+ for(i = 0; i < dialogOptCount; i++){
+ setFontColor(255, 255, 255);
+
+ // draw option
+ tmp = putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]);
+
+ // get coordinate information on option
dialogOptLoc[i][2] = offset.x + tmp;
dialogOptLoc[i][0] = offset.x - tmp;
dialogOptLoc[i][1] = y - SCREEN_HEIGHT / 4 + (fontSize + HLINE) * (i + 1);
return;
}
- for(i=0;i<dialogOptCount;i++){
- if(mouse.x > dialogOptLoc[i][0] &&
- mouse.x < dialogOptLoc[i][2] &&
- mouse.y > dialogOptLoc[i][1] &&
- mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize
+ // check for selected option
+ for(i = 0; i < dialogOptCount; i++){
+ if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] &&
+ mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){
dialogOptChosen = i + 1;
- goto DONE;
+ break;
+ }
+ }
++
++ if(dialogMerchant){
++ for(i = 0; i < 2; i++){
+ }
+ }
- DONE:
+
+ // handle important text
if(dialogImportant){
dialogImportant = false;
setFontSize(16);
- //toggleBlack();
}
- /*if(ui::fontSize != 16)
- setFontSize(16);*/
- // kill the dialog box
+ if(dialogMerchant) dialogMerchant = false;
dialogBoxExists = false;
}
-
+
void handleEvents(void){
static bool left=true,right=false;
static int heyOhLetsGo = 0;
pixels = new GLubyte[ 3 * SCREEN_WIDTH * SCREEN_HEIGHT];
glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-- static std::thread scr;
-- scr = std::thread(takeScreenshot,pixels);
-- scr.detach();
-- //takeScreenshot(pixels);
++ //static std::thread scr;
++ //scr = std::thread(takeScreenshot,pixels);
++ //scr.detach();
++ takeScreenshot(pixels);
std::cout << "Took screenshot" << std::endl;
break;