diff --git a/src/dialogue.c b/src/dialogue.c new file mode 100644 index 0000000..38b1865 --- /dev/null +++ b/src/dialogue.c @@ -0,0 +1,280 @@ +/** + * @file dialogue.c. + * + * @brief Handles dialogue stuff. + */ +#include +#include "lephisto.h" +#include "log.h" +#include "toolkit.h" +#include "pause.h" +#include "opengl.h" +#include "input.h" +#include "dialogue.h" + +/* Extern. */ +extern void main_loop(void); /* From lephisto.c */ + +/* Dialogues. */ +static glFont* dialogue_getSize(char* msg, int* w, int* h); +static void dialogue_alertClose(char* str); +static void dialogue_msgClose(char* str); +static void dialogue_YesNoClose(char* str); +static void dialogue_inputClose(char* str); +static void dialogue_inputCancel(char* str); + +/* Secondary loop hack. */ +static int loop_done; +static int toolkit_loop(void); + +/** + * @fn void dialogue_alert(const char* fmt, ...) + * + * @brief Display an alert popup with only an ok button and a message. + * @param fmt Printf stype message to display. + */ +void dialogue_alert(const char* fmt, ...) { + char msg[512]; + va_list ap; + unsigned int wdw; + int h; + + if(window_exists("Warning")) return; + + if(fmt == NULL) return; + else { /* Get the message. */ + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + } + + h = gl_printHeight(&gl_smallFont, 260, msg); + + wdw = window_create("Warning", -1, -1, 300, 90+h); + window_addText(wdw, 20, -30, 260, h, 0, "txtAlert", + &gl_smallFont, &cBlack, msg); + window_addButton(wdw, 135, 20, 50, 30, "btnOK", "OK", + dialogue_alertClose); +} + +/** + * @fn static void dialogue_alertClose(char* str) + * + * @brief Closes the alert dialogue. + * @param str Unused. + */ +static void dialogue_alertClose(char* str) { + (void)str; + if(window_exists("Warning")) + window_destroy(window_get("Warning")); +} + +/** + * @fn static glFont* dialogue_getSize(char* msg, int* w, int* h) + * + * @brief Get the size needed for the dialogue. + * @param msg Message of the dialogue. + * @param[out] w Get the width needed. + * @param[out] h Get the height needed. + */ +static glFont* dialogue_getSize(char* msg, int* w, int* h) { + glFont* font; + + font = &gl_smallFont; /* Try to use small font. */ + + (*h) = gl_printHeight(font, (*w)-40, msg); + if(strlen(msg) > 100) { /* Make font bigger for large texts. */ + font = &gl_defFont; + (*h) = gl_printHeight(font, (*w)-40, msg); + if((*h) > 200) (*w) += MIN((*h)-200, 600); /* Too big, so we make it wider. */ + (*h) = gl_printHeight(font, (*w)-40, msg); + } + return font; +} + +/* Displays an alert popup with only an ok button and a message. */ +static unsigned int msg_wid = 0; +void dialogue_msg(char* caption, const char* fmt, ...) { + char msg[4096]; + va_list ap; + int w, h; + glFont* font; + + if(msg_wid) return; + + if(fmt == NULL) return; + else { + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + } + + w = 300; /* Default width. */ + font = dialogue_getSize(msg, &w, &h); + + /* Create the window. */ + msg_wid = window_create(caption, -1, -1, w, 110 + h); + window_addText(msg_wid, 20, -40, w-40, h, 0, "txtMsg", + font, &cBlack, msg); + window_addButton(msg_wid, (w-50)/2, 20, 50, 30, "btnOK", "OK", + dialogue_msgClose); + + toolkit_loop(); +} + +static void dialogue_msgClose(char* str) { + (void)str; + window_destroy(msg_wid); + msg_wid = 0; + loop_done = 1; +} + +/* Run a dialogue with a Yes and No button, return 1 if yes, 0 for no. */ +static int yesno_result; +static unsigned int yesno_wid = 0; +int dialogue_YesNo(char* caption, const char* fmt, ...) { + char msg[4096]; + va_list ap; + int w, h; + glFont* font; + + if(yesno_wid) return -1; + + if(fmt == NULL) return -1; + else { /* Get the message. */ + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + } + + w = 300; + font = dialogue_getSize(msg, &w, &h); + + /* Create the window. */ + yesno_wid = window_create(caption, -1, -1, w, h+110); + + /* Text. */ + window_addText(yesno_wid, 20, -40, w-40, h, 0, "txtYesNo", + font, &cBlack, msg); + + /* Buttons. */ + window_addButton(yesno_wid, w/2-50-10, 20, 50, 30, "btnYes", "Yes", + dialogue_YesNoClose); + window_addButton(yesno_wid, w/2+10, 20, 50, 30, "btnNo", "No", + dialogue_YesNoClose); + + /* Tricky secondary loop. */ + toolkit_loop(); + + /* Return the result. */ + return yesno_result; +} + +static void dialogue_YesNoClose(char* str) { + /* Store the result. */ + if(strcmp(str, "btnYes")==0) yesno_result = 1; + else if(strcmp(str, "btnNo")==0) yesno_result = 0; + + /* Destroy the window. */ + window_destroy(yesno_wid); + yesno_wid = 0; + + loop_done = 1; +} + +/* Toolkit input boxes, returns the input. */ +static unsigned int input_wid = 0; +static int input_cancelled = 0; +char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { + char msg[512], *input; + va_list ap; + int h; + + if(input_wid) return NULL; + + if(fmt == NULL) return NULL; + else { /* Get the message. */ + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + } + + /* Start out not cancelled. */ + input_cancelled = 0; + + /* Get text height. */ + h = gl_printHeight(&gl_smallFont, 200, msg); + + /* Create Window. */ + input_wid = window_create(title, -1, -1, 240, h+140); + window_setAccept(input_wid, dialogue_inputClose); + window_setCancel(input_wid, dialogue_inputCancel); + + /* Input. */ + window_addText(input_wid, 30, -30, 200, h, 0, "txtInput", + &gl_smallFont, &cDConsole, msg); + window_addButton(input_wid, -20, 20, 80, 30, + "btnClose", "Done", dialogue_inputClose); + + /* Tricky secondary. */ + input = NULL; + while(!input_cancelled && (!input || + ((int) strlen(input) < min))) { /* Must be longer than min. */ + + if(input) { + dialogue_alert("Input must be at least %d characters long!", min); + free(input); + input = NULL; + } + + if(toolkit_loop() != 0) /* Error in loop -> quit. */ + return NULL; + + if(input_cancelled != 0) + input = NULL; + else + input = strdup(window_getInput(input_wid, "inpInput")); + } + + /* Cleanup plox. */ + window_destroy(input_wid); + input_wid = 0; + + return input; +} + +static void dialogue_inputClose(char* str) { + (void)str; + + /* Break the loop. */ + loop_done = 1; +} + +static void dialogue_inputCancel(char* str) { + input_cancelled = 1; + dialogue_inputClose(str); +} + +/* + * Spawns a secondary loop that only works until the toolkit dies, + * alot like the main while loop in lephisto.c + */ +static int toolkit_loop(void) { + SDL_Event event, quit = { .type = SDL_QUIT }; + + loop_done = 0; + while(!loop_done && toolkit) { + while(SDL_PollEvent(&event)) { /* Event loop. */ + if(event.type == SDL_QUIT) { /* Pass quit event to main engine. */ + loop_done = 1; + SDL_PushEvent(&quit); + return -1; + } + input_handle(&event); /* Handles all the events and player keybinds. */ + } + main_loop(); + } + + return 0; +} + diff --git a/src/dialogue.h b/src/dialogue.h new file mode 100644 index 0000000..0c484af --- /dev/null +++ b/src/dialogue.h @@ -0,0 +1,10 @@ +#pragma once + +/* + * Popups and alerts. + */ +void dialogue_alert(const char* ftm, ...); /* Does not pause execution. */ +void dialogue_msg(char* caption, const char* fmt, ...); +int dialogue_YesNo(char* caption, const char* fmt, ...); /* Yes = 1, No = 0. */ +char* dialogue_input(char* title, int min, int max, const char* fmt, ...); + diff --git a/src/land.c b/src/land.c index b184d98..4e39b5d 100644 --- a/src/land.c +++ b/src/land.c @@ -6,6 +6,7 @@ #include "lephisto.h" #include "log.h" #include "toolkit.h" +#include "dialogue.h" #include "player.h" #include "rng.h" #include "music.h" diff --git a/src/llua.c b/src/llua.c index 619d278..c1e2a2b 100644 --- a/src/llua.c +++ b/src/llua.c @@ -4,7 +4,7 @@ #include "lephisto.h" #include "rng.h" #include "ltime.h" -#include "toolkit.h" +#include "dialogue.h" #include "space.h" #include "land.h" #include "map.h" diff --git a/src/menu.c b/src/menu.c index 3577771..94e23e6 100644 --- a/src/menu.c +++ b/src/menu.c @@ -2,6 +2,7 @@ #include #include "toolkit.h" +#include "dialogue.h" #include "log.h" #include "lephisto.h" #include "pilot.h" diff --git a/src/player.c b/src/player.c index 9318c3d..6d1b9c5 100644 --- a/src/player.c +++ b/src/player.c @@ -21,6 +21,7 @@ #include "pause.h" #include "menu.h" #include "toolkit.h" +#include "dialogue.h" #include "mission.h" #include "misn_lua.h" #include "ltime.h" diff --git a/src/save.c b/src/save.c index a1f03a7..9231099 100644 --- a/src/save.c +++ b/src/save.c @@ -7,6 +7,7 @@ #include "xml.h" #include "player.h" #include "toolkit.h" +#include "dialogue.h" #include "menu.h" #include "lfile.h" #include "hook.h" diff --git a/src/toolkit.c b/src/toolkit.c index 8525025..0fb6e82 100644 --- a/src/toolkit.c +++ b/src/toolkit.c @@ -124,9 +124,6 @@ static glColour* toolkit_colLight = &cGrey90; static glColour* toolkit_col = &cGrey70; static glColour* toolkit_colDark = &cGrey30; -/* Extern. */ -extern void main_loop(void); /* lephisto.c */ -/* Static. */ /* Widgets. */ static Widget* window_newWidget(Window* w); static void widget_cleanup(Widget* widget); @@ -159,16 +156,6 @@ static void toolkit_clip(double x, double y, double w, double h); static void toolkit_unclip(void); static void toolkit_drawRect(double x, double y, double w, double h, glColour* c, glColour* lc); -/* Dialogues.. */ -static glFont* dialogue_getSize(char* msg, int* w, int* h); -static void dialogue_alertClose(char* str); -static void dialogue_msgClose(char* str); -static void dialogue_YesNoClose(char* str); -static void dialogue_inputClose(char* str); -static void dialogue_inputCancel(char* str); -/* Secondary loop hack. */ -static int loop_done; -static int toolkit_loop(void); /* Set the internal widget position. */ static void toolkit_setPos(Window* wdw, Widget* wgt, int x, int y) { @@ -1499,226 +1486,6 @@ static Widget* toolkit_getFocus(void) { return &wdw->widgets[wdw->focus]; } -void dialogue_alert(const char* fmt, ...) { - char msg[512]; - va_list ap; - unsigned int wdw; - int h; - - if(window_exists("Warning")) return; - - if(fmt == NULL) return; - else { - /* Get the message. */ - va_start(ap, fmt); - vsprintf(msg, fmt, ap); - va_end(ap); - } - - h = gl_printHeight(&gl_smallFont, 260, msg); - - /* Create window. */ - wdw = window_create("Warning", -1, -1, 300, 90+h); - - window_addText(wdw, 20, -30, 260, h, 0, "txtAlert", - &gl_smallFont, &cBlack, msg); - - window_addButton(wdw, 135, 20, 50, 30, "btnOK", "OK", - dialogue_alertClose); -} - -static void dialogue_alertClose(char* str) { - (void)str; - if(window_exists("Warning")) - window_destroy(window_get("Warning")); -} - -static glFont* dialogue_getSize(char* msg, int* w, int* h) { - glFont* font; - - font = &gl_smallFont; /* Try to use smallfont. */ - (*h) = gl_printHeight(font, (*w)-40, msg); - if(strlen(msg) > 100) { - /* Make font bigger for large text area's. */ - font = &gl_defFont; - (*h) = gl_printHeight(font, (*w)-40, msg); - if((*h) > 200) (*w) += MIN((*h)-200, 600); /* Too big, so we make it wider. */ - (*h) = gl_printHeight(font, (*w)-40, msg); - } - return font; -} - -/* Display an alert popup with only an OK button and a message. */ -static unsigned int msg_wid = 0; -void dialogue_msg(char* caption, const char* fmt, ...) { - char msg[4096]; - va_list ap; - int w, h; - glFont* font; - - if(msg_wid) return; - - if(fmt == NULL) return; - else { - /* Get the message. */ - va_start(ap, fmt); - vsprintf(msg, fmt, ap); - va_end(ap); - } - - w = 300; /* Default width. */ - font = dialogue_getSize(msg, &w, &h); - - /* Create the window. */ - msg_wid = window_create(caption, -1, -1, w, 110+h); - window_addText(msg_wid, 20, -40, w-40, h, 0, "txtMsg", - font, &cBlack, msg); - - window_addButton(msg_wid, (w-50)/2, 20, 50, 30, "btnOK", "OK", - dialogue_msgClose); - - toolkit_loop(); -} - -static void dialogue_msgClose(char* str) { - (void)str; - window_destroy(msg_wid); - msg_wid = 0; - loop_done = 1; -} - -/* Runs a dialogue with a Yes No button, return 1 if yes. */ -static int yesno_result; -static unsigned int yesno_wid = 0; -int dialogue_YesNo(char* caption, const char* fmt, ...) { - char msg[4096]; - va_list ap; - int w, h; - glFont* font; - - if(yesno_wid) return -1; - - if(fmt == NULL) return -1; - else { - /* Get the message. */ - va_start(ap, fmt); - vsprintf(msg, fmt, ap); - va_end(ap); - } - - w = 300; - font = dialogue_getSize(msg, &w, &h); - - /* Create window. */ - yesno_wid = window_create(caption, -1, -1, w, h+110); - /* Text. */ - window_addText(yesno_wid, 20, -40, w-40, h, 0, "txtYesNo", - font, &cBlack, msg); - /* Buttons. */ - window_addButton(yesno_wid, w/2-50-10, 20, 50, 30, "btnYes", "Yes", - dialogue_YesNoClose); - - window_addButton(yesno_wid, w/2+50+10, 20, 50, 30, "btnNo", "No", - dialogue_YesNoClose); - - /* Tricky secondary loop. */ - toolkit_loop(); - - /* Return the result. */ - return yesno_result; -} - -static void dialogue_YesNoClose(char* str) { - /* Store the result. */ - if(strcmp(str, "btnYes")==0) yesno_result = 1; - else if(strcmp(str, "btnNo")==0) yesno_result = 0; - - /* Destroy the window. */ - window_destroy(yesno_wid); - yesno_wid = 0; - - loop_done = 1; -} - -/* Toolkit input boxes, return input. */ -static unsigned int input_wid = 0; -static int input_cancelled = 0; -char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { - char msg[512], *input; - va_list ap; - int h; - - if(input_wid) return NULL; - - if(fmt == NULL) return NULL; - else { - /* Get the message. */ - va_start(ap, fmt); - vsprintf(msg, fmt, ap); - va_end(ap); - } - - /* Start out not cancelled. */ - input_cancelled = 0; - - /* Get text height. */ - h = gl_printHeight(&gl_smallFont, 200, msg); - - /* Create the window. */ - input_wid = window_create(title, -1, -1, 240, h+140); - window_setAccept(input_wid, dialogue_inputClose); - window_setCancel(input_wid, dialogue_inputCancel); - /* Text. */ - window_addText(input_wid, 30, -30, 200, h, 0, "txtInput", - &gl_smallFont, &cDConsole, msg); - - /* Input. */ - window_addInput(input_wid, 20, -50-h, 200, 20, "inpInput", max, 1); - - /*Button. */ - window_addButton(input_wid, -20, 20, 80, 30, - "btnClose", "Done", dialogue_inputClose); - - /* Tricky secondary loop. */ - input = NULL; - while(!input_cancelled && (!input || - ((int)strlen(input) < min))) { /* Must be longer then min. */ - /* Must be longer than min. */ - if(input) { - dialogue_alert("Input must be at least %d characters long!", min); - free(input); - input = NULL; - } - - if(toolkit_loop() != 0) /* Error in loop -> quit. */ - return NULL; - - /* Save the input. */ - if(input_cancelled != 0) - input = NULL; - else - input = strdup(window_getInput(input_wid, "inpInput")); - } - - /* Cleanup. */ - window_destroy(input_wid); - input_wid = 0; - - return input; -} - -static void dialogue_inputClose(char* str) { - (void)str; - - /* Break the loop. */ - loop_done = 1; -} - -static void dialogue_inputCancel(char* str) { - input_cancelled = 1; - dialogue_inputClose(str); -} - /* Init. */ int toolkit_init(void) { windows = malloc(sizeof(Window)*MIN_WINDOWS); @@ -1735,26 +1502,3 @@ void toolkit_exit(void) { free(windows); } -/* Spawns a secondary loop that only works until the toolkit dies. */ -/* A lot like the main while loop in lephisto.c. */ -static int toolkit_loop(void) { - SDL_Event event, quit = { .type = SDL_QUIT }; - - loop_done = 0; - while(!loop_done && toolkit) { - while(SDL_PollEvent(&event)) { - /* Event loopz. */ - if(event.type == SDL_QUIT) { - /* Pass quit event to main engine. */ - loop_done = 1; - SDL_PushEvent(&quit); - return 1; - } - /* Handles all the events and player keybinds. */ - input_handle(&event); - } - main_loop(); - } - return 0; -} - diff --git a/src/toolkit.h b/src/toolkit.h index 2957b41..ca010f6 100644 --- a/src/toolkit.h +++ b/src/toolkit.h @@ -43,15 +43,6 @@ void window_addInput(const unsigned int wid, const int w, const int h, char* name, const int max, const int oneline); -/* Popups and alerts. */ - -/* Does not pause execution. */ -void dialogue_alert(const char* fmt, ...); -void dialogue_msg(char* caption, const char* fmt, ...); -/* Yes = 1, No = 0. */ -int dialogue_YesNo(char* caption, const char* fmt, ...); -char* dialogue_input(char* title, int min, int max, const char* fmt, ...); - /* Modification. */ void window_setAccept(const unsigned int wid, void(*fptr)(char*)); void window_setCancel(const unsigned int wid, void(*cancel)(char*));