From f8701e4bdc6fe95183396d14e914506549973eee Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Tue, 8 Apr 2014 23:48:35 +0100
Subject: [PATCH] [Add] Added options menu for audio and faders.

---
 src/menu.c    |   5 +-
 src/options.c |  64 +++++++++++++++++-
 src/options.h |   1 +
 src/toolkit.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/toolkit.h |  22 ++++++
 5 files changed, 270 insertions(+), 6 deletions(-)

diff --git a/src/menu.c b/src/menu.c
index 90eeed0..e441049 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -45,7 +45,7 @@
 #define DEATH_WIDTH         130   /**< Death menu width. */
 #define DEATH_HEIGHT        150   /**< Death menu height. */
 
-#define OPTIONS_WIDTH       249   /**< Options menu width. */
+#define OPTIONS_WIDTH       260   /**< Options menu width. */
 #define OPTIONS_HEIGHT       90   /**< Options menu height. */
 
 #define BUTTON_WIDTH        90    /**< Button width, standard across menus. */
@@ -647,6 +647,9 @@ void menu_options(void) {
   window_addButton(wid, -20 - (BUTTON_WIDTH+20), 20,
       BUTTON_WIDTH, BUTTON_HEIGHT,
       "btnKeybinds", "Keybindings", (void(*)(unsigned int,char*))opt_menuKeybinds);
+  window_addButton(wid, -20 - 2 * (BUTTON_WIDTH+20), 20,
+      BUTTON_WIDTH, BUTTON_HEIGHT,
+      "btnAudio", "Audio", (void(*)(unsigned int, char*))opt_menuAudio);
   menu_Open(MENU_OPTIONS);
 }
 
diff --git a/src/options.c b/src/options.c
index ace4c66..b50cba1 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1,7 +1,7 @@
 /**
- * @file menu.h
+ * @file options.c
  *
- * @brief Handle the important game menus.
+ * @brief Options menu.
  */
 
 #include <string.h>
@@ -11,11 +11,16 @@
 #include "lephisto.h"
 #include "input.h"
 #include "toolkit.h"
+#include "sound.h"
+#include "music.h"
 #include "options.h"
 
 #define KEYBINDS_WIDTH   440   /**< Options menu width. */
 #define KEYBINDS_HEIGHT  300   /**< Options menu height. */
 
+#define AUDIO_WIDTH      340   /**< Options menu width. */
+#define AUDIO_HEIGHT     200   /**< Options menu height. */
+
 #define BUTTON_WIDTH    90    /**< Button width, standard across menus. */
 #define BUTTON_HEIGHT   30    /**< Button height, standard across menus. */
 
@@ -25,6 +30,9 @@ extern const char* keybindNames[]; /* input.c */
 static const char* modToText(SDLMod mod);
 static void menuKeybinds_update(unsigned int wid, char* name);
 
+static void opt_setSFXLevel(unsigned int wid, char* str);
+static void opt_setMusicLevel(unsigned int wid, char* str);
+
 /**
  * @brief Opens the keybindings menu.
  */
@@ -163,3 +171,55 @@ static void menuKeybinds_update(unsigned int wid, char* name) {
   window_modifyText(wid, "txtDesc", buf);
 }
 
+/**
+ * @brief Callback to set the sound level.
+ */
+static void opt_setSFXLevel(unsigned int wid, char* str) {
+  double vol;
+  vol = window_getFaderValue(wid, str);
+  sound_volume(vol);
+}
+
+/**
+ * @brief Callback to set the music level.
+ */
+static void opt_setMusicLevel(unsigned int wid, char* str) {
+  double vol;
+  vol = window_getFaderValue(wid, str);
+  music_volume(vol);
+}
+
+/**
+ * @brief Opens the audio settings menu.
+ */
+void opt_menuAudio(void) {
+  unsigned int wid;
+
+  /* Create the window. */
+  wid = window_create("Audio", -1, -1, AUDIO_WIDTH, AUDIO_HEIGHT);
+
+  /* Sound fader. */
+  if(!sound_disabled) {
+    window_addFader(wid, 20, -40, 160, 20, "fadSound", 0., 1.,
+        sound_defVolume, opt_setSFXLevel);
+    window_addText(wid, 200, -40, AUDIO_WIDTH-220, 20, 1, "txtSound",
+        NULL, NULL, "Sound Volume");
+  } else
+    window_addText(wid, 200, -40, AUDIO_WIDTH-220, 20, 1, "txtSound",
+        NULL, NULL, "Sound Disabled");
+
+  /* Music fader. */
+  if(!music_disabled) {
+    window_addFader(wid, 20, -80, 160, 20, "fadMusic", 0., 1.,
+        music_defVolume, opt_setMusicLevel);
+    window_addText(wid, 200, -80, AUDIO_WIDTH-220, 20, 1, "txtMusic",
+        NULL, NULL, "Music Volume");
+  } else
+    window_addText(wid, 200, -80, AUDIO_WIDTH-220, 20, 1, "txtMusic",
+        NULL, NULL, "Music Disabled");
+
+  /* Close button. */
+  window_addButton(wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
+      "btnClose", "Close", window_close);
+}
+
diff --git a/src/options.h b/src/options.h
index 7a06f46..f5f7f84 100644
--- a/src/options.h
+++ b/src/options.h
@@ -1,4 +1,5 @@
 #pragma once
 
 void opt_menuKeybinds(void);
+void opt_menuAudio(void);
 
diff --git a/src/toolkit.c b/src/toolkit.c
index 74a5f2a..5320071 100644
--- a/src/toolkit.c
+++ b/src/toolkit.c
@@ -25,7 +25,9 @@ typedef enum WidgetType_ {
   WIDGET_RECT,
   WIDGET_CUST,
   WIDGET_INPUT,
-  WIDGET_IMAGEARRAY
+  WIDGET_IMAGEARRAY,
+  WIDGET_SCROLLBAR,
+  WIDGET_FADER
 } WidgetType;
 
 typedef enum WidgetStatus_ {
@@ -101,6 +103,16 @@ typedef struct Widget_ {
       int ih;               /**< Image height to use. */
       void(*fptr)(unsigned int, char*);   /**< Modify callback - triggered on selection. */
     } iar; /**< WIDGET_IMAGEARRAY */
+    struct {
+      double value; /**< Current value. */
+    } scb; /**< WIDGET_SCROLLBAR */
+
+    struct {
+      double value;   /**< Current value. */
+      double min;     /**< Minimum value. */
+      double max;     /**< Maximum value. */
+      void(*fptr)(unsigned int, char*); /**< Modify callback - triggered on value change. */
+    } fad; /**< WIDGET_FADER */
   } dat;
 } Widget;
 
@@ -162,6 +174,7 @@ static Widget* toolkit_getFocus(void);
 static void toolkit_listScroll(Widget* wgt, int direction);
 static void toolkit_listFocus(Widget* lst, double bx, double by);
 static void toolkit_imgarrFocus(Widget* iar, double dx, double by);
+static void toolkit_faderSetValue(Widget* fad, double value);
 /* Render. */
 static void window_render(Window* w);
 static void toolkit_renderButton(Widget* btn, double bx, double by);
@@ -172,6 +185,8 @@ static void toolkit_renderRect(Widget* rct, double bx, double by);
 static void toolkit_renderCust(Widget* cst, double bx, double by);
 static void toolkit_renderInput(Widget* inp, double bx, double by);
 static void toolkit_renderImageArray(Widget* iar, double bx, double by);
+static void toolkit_renderScrollbar(Widget* scb, double bx, double by);
+static void toolkit_renderFader(Widget* fad, double bx, double by);
 static void toolkit_drawOutline(double x, double y, double w,
                                 double h, double b, glColour* c, glColour* lc);
 static void toolkit_drawScrollbar(double x, double y, double w, double h, double pos);
@@ -420,6 +435,60 @@ void window_addImageArray(const unsigned int wid,
     toolkit_nextFocus();
 }
 
+void window_addScrollbar(const unsigned int wid,
+    const int x, const int y, /* Position. */
+    const int w, const int h, /* Size. */
+    char* name, double value) {
+
+  Window* wdw = window_wget(wid);
+  Widget* wgt = window_newWidget(wdw);
+
+  /* Genetic. */
+  wgt->type = WIDGET_SCROLLBAR;
+  wgt->name = strdup(name);
+
+  /* Specific. */
+  wgt->dat.scb.value = value;
+
+  /* Position/size. */
+  wgt->w = (double)w;
+  wgt->h = (double)h;
+  toolkit_setPos(wdw, wgt, x, y);
+
+  if(wdw->focus == -1) /* Initialize the focus. */
+    toolkit_nextFocus();
+}
+
+void window_addFader(const unsigned int wid,
+    const int x, const int y, /* Position. */
+    const int w, const int h, /* Size, if w > h fader is horizontal, else vertical. */
+    char* name, const double min, const double max, /* Name, min/max values. */
+    const double def,
+    void(*call)(unsigned int, char*)) {
+  
+  Window* wdw = window_wget(wid);
+  Widget* wgt = window_newWidget(wdw);
+
+  /* Generic. */
+  wgt->type = WIDGET_FADER;
+  wgt->name = strdup(name);
+
+  /* Specific. */
+  wgt->dat.fad.value = min;
+  wgt->dat.fad.min = min;
+  wgt->dat.fad.max = max;
+  wgt->dat.fad.value = MAX(min, MIN(max,def));
+  wgt->dat.fad.fptr = call;
+
+  /* Position/size. */
+  wgt->w = (double)w;
+  wgt->h = (double)h;
+  toolkit_setPos(wdw, wgt, x, y);
+
+  if(wdw->focus == -1) /* Initialize the focus. */
+    toolkit_nextFocus();
+}
+
 /* Return pointer to newly allocated widget. */
 static Widget* window_newWidget(Window* w) {
   Widget* wgt = NULL;
@@ -515,6 +584,33 @@ void window_imgColour(const unsigned int wid, char* name, glColour* colour) {
   wgt->dat.img.colour = colour;
 }
 
+/**
+ * Set scrollbar value.
+ */
+void window_scrollbarValue(const unsigned int wid,
+    char* name, double value) {
+  Widget* wgt = window_getwgt(wid, name);
+
+  wgt->dat.scb.value = value;
+}
+
+/* Set fader value. */
+void window_faderValue(const unsigned int wid,
+    char* name, double value) {
+  Widget* wgt = window_getwgt(wid, name);
+  toolkit_faderSetValue(wgt, value);
+}
+
+/* Set minimum and maximum fader values. */
+void window_faderBounds(const unsigned int wid,
+    char* name, double min, double max) {
+  Widget* wgt = window_getwgt(wid, name);
+  wgt->dat.fad.min = min;
+  wgt->dat.fad.max = max;
+  double value = MAX(MIN(value, wgt->dat.fad.max), wgt->dat.fad.min);
+  toolkit_faderSetValue(wgt, value);
+}
+
 glTexture* window_getImage(const unsigned int wid, char* name) {
   Widget* wgt = window_getwgt(wid, name);
   return (wgt) ? wgt->dat.img.image : NULL;
@@ -526,6 +622,18 @@ char* window_getInput(const unsigned int wid, char* name) {
   return(wgt) ? wgt->dat.inp.input : NULL;
 }
 
+/* Get the value from a scrollbar widget. */
+double window_getScrollbarValue(const unsigned int wid, char* name) {
+  Widget* wgt = window_getwgt(wid, name);
+  return (wgt) ? wgt->dat.scb.value : 0.;
+}
+
+/* Get value of fader. */
+double window_getFaderValue(const unsigned int wid, char* name) {
+  Widget* wgt = window_getwgt(wid, name);
+  return (wgt) ? wgt->dat.fad.value : 0.;
+}
+
 /* Check if a window exists. */
 int window_exists(const char* wdwname) {
   int i;
@@ -1059,6 +1167,13 @@ static void window_render(Window* w) {
     case WIDGET_IMAGEARRAY:
       toolkit_renderImageArray(&w->widgets[i], x, y);
       break;
+
+    case WIDGET_SCROLLBAR:
+      toolkit_renderScrollbar(&w->widgets[i], x, y);
+      break;
+      
+    case WIDGET_FADER:
+      toolkit_renderFader(&w->widgets[i], x, y);
     }
   }
   /* Focus widget. */
@@ -1387,6 +1502,53 @@ static void toolkit_drawScrollbar(double x, double y, double w, double h, double
   toolkit_drawOutline(x, sy, w, 30., 0., toolkit_colDark, NULL);
 }
 
+/**
+ * @brief Render a scrollbar.
+ *    @param scb WIDGET_SCROLLBAR widget to render.
+ *    @param bx Base X position.
+ *    @param by Base Y position.
+ */
+static void toolkit_renderScrollbar(Widget* scb, double bx, double by) {
+  toolkit_drawScrollbar(bx + scb->x, by + scb->y,
+      scb->w, scb->h,
+      scb->dat.scb.value);
+}
+
+/**
+ * @brief Render a fader.
+ *    @param fad WIDGET_FADER widget to render.
+ *    @param bx Base X position.
+ *    @param by Base Y position.
+ */
+static void toolkit_renderFader(Widget* fad, double bx, double by) {
+  double pos;
+  double w, h;
+  double tx, ty, tw, th;
+  double kx, ky, kw, kh;
+
+  /* Some values. */
+  pos = fad->dat.fad.value / (fad->dat.fad.max - fad->dat.fad.min);
+  w = fad->w;
+  h = fad->h;
+
+  /* Track. */
+  tx = bx + fad->x + (h > w ? (w - 5.) / 2 : 0);
+  ty = by + fad->y + (h < w ? (h - 5.) / 2 : 0);
+  tw = (h < w ? w : 5.);
+  th = (h > w ? h : 5.);
+  toolkit_drawRect(tx, ty, tw, th, toolkit_colDark, toolkit_colDark);
+
+  /* Knob. */
+  kx = bx + fad->x + (h < w ? w * pos - 5. : 0);
+  ky = by + fad->y + (h > w ? h * pos - 5. : 0);
+  kw = (h < w ? 15. : w);
+  kh = (h > w ? 15. : h);
+
+  /* Draw. */
+  toolkit_drawRect(kx, ky, kw, kh, toolkit_colDark, toolkit_colLight);
+  toolkit_drawOutline(kx, ky, kw, kh, 1., &cBlack, toolkit_colDark);
+}
+
 /* Handle input for input widget. */
 static int toolkit_inputInput(Uint8 type, Widget* inp, SDLKey key) {
   int n;
@@ -1488,6 +1650,7 @@ int toolkit_input(SDL_Event* event) {
 static int mouse_down = 0;
 static void toolkit_mouseEvent(SDL_Event* event) {
   int i;
+  double d;
   double x, y, rel_x, rel_y;
   Window* w;
   Widget* wgt, *wgt_func;
@@ -1541,6 +1704,12 @@ static void toolkit_mouseEvent(SDL_Event* event) {
               toolkit_listMove(wgt, y-wgt->y);
             if(wgt->type == WIDGET_IMAGEARRAY)
               toolkit_imgarrMove(wgt, rel_y);
+            if(wgt->type == WIDGET_SCROLLBAR)
+              wgt->dat.scb.value -= rel_y / wgt->h;
+            if(wgt->type == WIDGET_FADER) {
+              d = (wgt->w > wgt->h) ? rel_x / wgt->w : rel_y / wgt->h;
+              toolkit_faderSetValue(wgt, wgt->dat.fad.value + d);
+            }
           }
           break;
         case SDL_MOUSEBUTTONDOWN:
@@ -1838,8 +2007,17 @@ static void toolkit_listScroll(Widget* wgt, int direction) {
 }
 
 /**
- * @fn char* toolkit_getList(const unsigned int wid, char* name)
- *
+ * @brief Change fader value.
+ */
+static void toolkit_faderSetValue(Widget* fad, double value) {
+  Window* w = &windows[nwindows-1];
+  value = MAX(MIN(value, fad->dat.fad.max), fad->dat.fad.min);
+  fad->dat.fad.value = value;
+  if(fad->dat.fad.fptr != NULL)
+    (*fad->dat.fad.fptr)(w->id, fad->name);
+}
+
+/**
  * @brief Get what is selected currently in a list.
  *
  * List included Image Array.
diff --git a/src/toolkit.h b/src/toolkit.h
index 1cd2d6b..ced72f2 100644
--- a/src/toolkit.h
+++ b/src/toolkit.h
@@ -50,6 +50,18 @@ void window_addImageArray(const unsigned int wid,
                           glTexture** tex, char** caption, int nelem, /* Elements. */
                           void(*call)(unsigned int, char*));
 
+void window_addScrollbar(const unsigned int wid,
+    const int x, const int y,   /* Position. */
+    const int w, const int h,   /* Size. */
+    char* name, double value);  /* Value. */
+
+void window_addFader(const unsigned int wid,
+    const int x, const int y,   /* Position. */
+    const int w, const int h,   /* Size, if w > h fader is horizontal, else vertical. */
+    char* name, const double min, const double max, /* name, min * max values. */
+    const double def, /* Default pos. */
+    void(*call)(unsigned int, char*)); /* Function to call on value change. */
+
 /* Modification. */
 void window_setAccept(const unsigned int wid, void(*fptr)(unsigned int, char*));
 void window_setCancel(const unsigned int wid, void(*cancel)(unsigned int, char*));
@@ -61,6 +73,13 @@ void window_enableButton(const unsigned int wid, char* name);
 /* Image. */
 void window_modifyImage(const unsigned int wid, char* name, glTexture* image);
 void window_imgColour(const unsigned int wid, char* name, glColour* colour);
+/* Scroll bar. */
+void window_scrollbarValue(const unsigned int wid,
+    char* name, double value);
+void faderValue(const unsigned int wid,
+    char* name, double value);
+void faderBounds(const unsigned int wid,
+    char* name, double min, double max);
 
 /* Get. */
 /* Generic. */
@@ -77,6 +96,9 @@ char* toolkit_getList(const unsigned int wid, char* name);
 int toolkit_getListPos(const unsigned int wid, char* name);
 glTexture* window_getImage(const unsigned int wid, char* name);
 
+double window_getScrollbarValue(const unsigned int wid, char* name);
+double window_getFaderValue(const unsigned wid, char* name);
+
 /* Destroy window. */
 void window_close(unsigned int wid, char* str);
 void window_destroy(const unsigned int wid);