Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
71 KB
Referenced Files
None
Subscribers
None
diff --git a/src/GUIObject.cpp b/src/GUIObject.cpp
index 859d418..eac6eea 100644
--- a/src/GUIObject.cpp
+++ b/src/GUIObject.cpp
@@ -1,670 +1,670 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GUIObject.h"
#include <iostream>
#include <list>
using namespace std;
//Set the GUIObjectRoot to NULL.
GUIObject* GUIObjectRoot=NULL;
//Initialise the event queue.
list<GUIEvent> GUIEventQueue;
void GUIObjectHandleEvents(bool kill){
//Check if user resizes the window.
if(event.type==SDL_VIDEORESIZE){
//onVideoResize();
//Don't let other objects process this event (?)
return;
}
//Make sure that GUIObjectRoot isn't null.
if(GUIObjectRoot)
GUIObjectRoot->handleEvents();
//Check for SDL_QUIT.
if(event.type==SDL_QUIT && kill){
//We get a quit event so enter the exit state.
setNextState(STATE_EXIT);
delete GUIObjectRoot;
GUIObjectRoot=NULL;
return;
}
//Keep calling events until there are none left.
while(!GUIEventQueue.empty()){
//Get one event and remove it from the queue.
GUIEvent e=GUIEventQueue.front();
GUIEventQueue.pop_front();
//If an eventCallback exist call it.
if(e.eventCallback){
e.eventCallback->GUIEventCallback_OnEvent(e.name,e.obj,e.eventType);
}
}
//We empty the event queue just to be sure.
GUIEventQueue.clear();
}
GUIObject::~GUIObject(){
if(cache){
SDL_FreeSurface(cache);
cache=NULL;
}
//We need to delete every child we have.
for(unsigned int i=0;i<childControls.size();i++){
delete childControls[i];
}
//Deleted the childs now empty the childControls vector.
childControls.clear();
}
bool GUIObject::handleEvents(int x,int y,bool enabled,bool visible,bool processed){
//Boolean if the event is processed.
bool b=processed;
//The GUIObject is only enabled when he and his parent are enabled.
enabled=enabled && this->enabled;
//The GUIObject is only enabled when he and his parent are enabled.
visible=visible && this->visible;
//Get the absolute position.
x+=left-gravityX;
y+=top;
//Type specific event handling.
switch(type){
case GUIObjectButton:
//Set state to 0.
state=0;
//Only check for events when the object is both enabled and visible.
if(enabled&&visible){
//The mouse location (x=i, y=j) and the mouse button (k).
int i,j,k;
k=SDL_GetMouseState(&i,&j);
//Check if the mouse is inside the GUIObject.
if(i>=x&&i<x+width&&j>=y&&j<y+height){
//We have hover so set state to one.
state=1;
//Check for a mouse button press.
if(k&SDL_BUTTON(1))
state=2;
//Check if there's a mouse press and the event hasn't been already processed.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT && !b){
//If event callback is configured then add an event to the queue.
if(eventCallback){
GUIEvent e={eventCallback,name,this,GUIEventClick};
GUIEventQueue.push_back(e);
}
//Event has been processed.
b=true;
}
}
}
break;
case GUIObjectCheckBox:
//Set state to 0.
state=0;
//Only check for events when the object is both enabled and visible.
if(enabled&&visible){
//The mouse location (x=i, y=j) and the mouse button (k).
int i,j,k;
k=SDL_GetMouseState(&i,&j);
//Check if the mouse is inside the GUIObject.
if(i>=x&&i<x+width&&j>=y&&j<y+height){
//We have hover so set state to one.
state=1;
//Check for a mouse button press.
if(k&SDL_BUTTON(1))
state=2;
//Check if there's a mouse press and the event hasn't been already processed.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT && !b){
//It's a checkbox so toggle the value.
value=value?0:1;
//If event callback is configured then add an event to the queue.
if(eventCallback){
GUIEvent e={eventCallback,name,this,GUIEventClick};
GUIEventQueue.push_back(e);
}
//Event has been processed.
b=true;
}
}
}
break;
case GUIObjectTextBox:
//NOTE: We don't reset the state to have a "focus" effect.
//Only check for events when the object is both enabled and visible.
if(enabled&&visible){
//Check if there's a key press and the event hasn't been already processed.
if(state==2 && event.type==SDL_KEYDOWN && !b){
//Get the keycode.
int key=(int)event.key.keysym.unicode;
//Check if the key is supported.
if(key>=32&&key<=126){
//Add the key to the text after the carrot.
caption.insert((size_t)value,1,char(key));
value=clamp(value+1,0,caption.length());
//If there is an event callback then call it.
if(eventCallback){
GUIEvent e={eventCallback,name,this,GUIEventChange};
GUIEventQueue.push_back(e);
}
}else if(event.key.keysym.sym==SDLK_BACKSPACE){
//We need to remove a character so first make sure that there is text.
if(caption.length()>0&&value>0){
//Remove the character before the carrot.
value=clamp(value-1,0,caption.length());
caption.erase((size_t)value,1);
this->key=SDLK_BACKSPACE;
keyHoldTime=0;
keyTime=5;
//If there is an event callback then call it.
if(eventCallback){
GUIEvent e={eventCallback,name,this,GUIEventChange};
GUIEventQueue.push_back(e);
}
}
}else if(event.key.keysym.sym==SDLK_DELETE){
//We need to remove a character so first make sure that there is text.
if(caption.length()>0){
//Remove the character after the carrot.
value=clamp(value,0,caption.length());
caption.erase((size_t)value,1);
this->key=SDLK_DELETE;
keyHoldTime=0;
keyTime=5;
//If there is an event callback then call it.
if(eventCallback){
GUIEvent e={eventCallback,name,this,GUIEventChange};
GUIEventQueue.push_back(e);
}
}
}else if(event.key.keysym.sym==SDLK_RIGHT){
value=clamp(value+1,0,caption.length());
this->key=SDLK_RIGHT;
keyHoldTime=0;
keyTime=5;
}else if(event.key.keysym.sym==SDLK_LEFT){
value=clamp(value-1,0,caption.length());
this->key=SDLK_LEFT;
keyHoldTime=0;
keyTime=5;
}
//The event has been processed.
b=true;
}else if(state==2 && event.type==SDL_KEYUP && !b){
//Check if released key is the same as the holded key.
if(event.key.keysym.sym==key){
//It is so stop the key.
key=-1;
}
}
//The mouse location (x=i, y=j) and the mouse button (k).
int i,j,k;
k=SDL_GetMouseState(&i,&j);
//Check if the mouse is inside the GUIObject.
if(i>=x&&i<x+width&&j>=y&&j<y+height){
//We can only increase our state. (nothing->hover->focus).
if(state!=2){
state=1;
}
//Also update the cursor type.
currentCursor=CURSOR_CARROT;
//Check for a mouse button press.
if(k&SDL_BUTTON(1)){
//We have focus.
state=2;
//Move carrot to the place clicked
int click=i-x;
if(!cache){
value=0;
}else if(click>cache->w){
value=caption.length();
}else{
unsigned int wid=0;
for(unsigned int i=0;i<caption.length();i++){
int advance;
TTF_GlyphMetrics(fontText,caption[i],NULL,NULL,NULL,NULL,&advance);
wid+=advance;
if(click<(int)wid-(int)advance/2){
value=i;
break;
}
}
}
}
}else{
//The mouse is outside the TextBox.
//If we don't have focus but only hover we lose it.
if(state==1){
state=0;
}
//If it's a click event outside the textbox then we blur.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT){
//Set state to 0.
state=0;
}
}
}
break;
}
//Also let the children handle their events.
for(unsigned int i=0;i<childControls.size();i++){
bool b1=childControls[i]->handleEvents(x,y,enabled,visible,b);
//The event is processed when either our or the childs is true (or both).
b=b||b1;
}
return b;
}
//Found on gmane.comp.lib.sdl mailing list, see: http://comments.gmane.org/gmane.comp.lib.sdl/33664
//Original code by "Patricia Curtis" and later modified by "Jason"
static void SetSurfaceTrans(SDL_Surface* Src,double PercentTrans){
Uint8 Sbpp = Src->format->BytesPerPixel;
Uint8 *Sbits;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int amask = 0x000000ff;
int cmask = 0xffffff00;
#else
int amask = 0xff000000;
int cmask = 0x00ffffff;
int Shift = 24;
#endif
int x,y;
Uint32 Pixels;
Uint32 Alpha;
for(y=0;y<Src->h;y++)
{
for(x=0;x<Src->w;x++)
{
Sbits = ((Uint8 *)Src->pixels+(y*Src->pitch)+(x*Sbpp));
Pixels = *((Uint32 *)(Sbits));
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Alpha = Pixels & mask;
#else
Alpha = (Pixels&amask)>>Shift;
#endif
Alpha*=PercentTrans;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
*((Uint32 *)(Sbits)) = (Pixels & cmask)|Alpha;
#else
*((Uint32 *)(Sbits)) = (Pixels & cmask)|(Alpha<<Shift);
#endif
}
}
}
void GUIObject::render(int x,int y,bool draw){
//Rectangle the size of the GUIObject, used to draw borders.
SDL_Rect r;
//There's no need drawing the GUIObject when it's invisible.
if(!visible)
return;
//Get the absolute x and y location.
x+=left;
y+=top;
//Check if the enabled state changed or the caption, if so we need to clear the (old) cache.
if(enabled!=cachedEnabled || caption.compare(cachedCaption)!=0 || width<=0){
//Free the cache.
SDL_FreeSurface(cache);
cache=NULL;
//And cache the new values.
cachedEnabled=enabled;
cachedCaption=caption;
//Finally resize the widget
if(autoWidth)
width=-1;
}
//Now do the type specific rendering.
switch(type){
case GUIObjectLabel:
{
//The rectangle is simple.
r.x=x;
r.y=y;
r.w=width;
r.h=height;
//We don't draw a background and/or border since that label is transparent.
//Get the caption and make sure it isn't empty.
const char* lp=caption.c_str();
if(lp!=NULL && lp[0]){
//Render the text using the small font.
if(cache==NULL){
SDL_Color color;
if(inDialog)
color=themeTextColorDialog;
else
color=themeTextColor;
cache=TTF_RenderUTF8_Blended(fontText,lp,color);
if(width<=0)
width=cache->w;
}
if(draw){
if(gravity==GUIGravityCenter)
gravityX=(width-cache->w)/2;
else if(gravity==GUIGravityRight)
- gravityX=width+cache->w;
+ gravityX=width-cache->w;
else
gravityX=0;
//Center the text vertically and draw it to the screen.
r.y=y+(height - cache->h)/2;
r.x+=gravityX;
SDL_BlitSurface(cache,NULL,screen,&r);
}
}
}
break;
case GUIObjectCheckBox:
{
//The rectangle is simple.
r.x=x;
r.y=y;
r.w=width;
r.h=height;
//Get the text.
const char* lp=caption.c_str();
//Make sure it isn't empty.
if(lp!=NULL && lp[0]){
//We render black text.
if(!cache){
SDL_Color color;
if(inDialog)
color=themeTextColorDialog;
else
color=themeTextColor;
cache=TTF_RenderUTF8_Blended(fontText,lp,color);
}
if(draw){
//Calculate the location, center it vertically.
r.x=x;
r.y=y+(height - cache->h)/2;
//Draw the text and free the surface.
SDL_BlitSurface(cache,NULL,screen,&r);
}
}
if(draw){
//Draw the check (or not).
SDL_Rect r1={0,0,16,16};
if(value==1||value==2)
r1.x=value*16;
r.x=x+width-20;
r.y=y+(height-16)/2;
SDL_BlitSurface(bmGUI,&r1,screen,&r);
}
}
break;
case GUIObjectButton:
{
//Get the text.
const char* lp=caption.c_str();
//Make sure the text isn't empty.
if(lp!=NULL && lp[0]){
if(!cache){
SDL_Color color;
if(inDialog)
color=themeTextColorDialog;
else
color=themeTextColor;
if(!smallFont)
cache=TTF_RenderUTF8_Blended(fontGUI,lp,color);
else
cache=TTF_RenderUTF8_Blended(fontGUISmall,lp,color);
if(!enabled)
SetSurfaceTrans(cache,0.5);
if(width<=0){
width=cache->w+50;
if(gravity==GUIGravityCenter){
gravityX=int(width/2);
}else if(gravity==GUIGravityRight){
gravityX=width;
}else{
gravityX=0;
}
}
}
if(draw){
//Center the text both vertically as horizontally.
r.x=x-gravityX+(width-cache->w)/2;
r.y=y+(height-cache->h)/2-GUI_FONT_RAISE;
//Check if the arrows don't fall of.
if(cache->w+32<=width){
//Create a rectangle that selects the right image from bmGUI,
SDL_Rect r2={64,0,16,16};
if(state==1){
if(inDialog){
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w+5,y+2,arrowLeft2,screen,NULL);
applySurface(x-gravityX+(width-cache->w)/2-25,y+2,arrowRight2,screen,NULL);
}else{
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w+5,y+2,arrowLeft1,screen,NULL);
applySurface(x-gravityX+(width-cache->w)/2-25,y+2,arrowRight1,screen,NULL);
}
}else if(state==2){
if(inDialog){
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w,y+2,arrowLeft2,screen,NULL);
applySurface(x-gravityX+(width-cache->w)/2-20,y+2,arrowRight2,screen,NULL);
}else{
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w,y+2,arrowLeft1,screen,NULL);
applySurface(x-gravityX+(width-cache->w)/2-20,y+2,arrowRight1,screen,NULL);
}
}
}
//Draw the text and free the surface.
SDL_BlitSurface(cache,NULL,screen,&r);
}
}
}
break;
case GUIObjectTextBox:
{
//FIXME: Logic in the render method since that is update constant.
if(key!=-1){
//Increase the key time.
keyHoldTime++;
//Make sure the deletionTime isn't to short.
if(keyHoldTime>=keyTime){
keyHoldTime=0;
keyTime--;
if(keyTime<1)
keyTime=1;
//Now check the which key it was.
switch(key){
case SDLK_BACKSPACE:
{
//Remove the character before the carrot.
value=clamp(value-1,0,caption.length());
caption.erase((size_t)value,1);
break;
}
case SDLK_DELETE:
{
//Remove the character after the carrot.
value=clamp(value,0,caption.length());
caption.erase((size_t)value,1);
break;
}
case SDLK_LEFT:
{
value=clamp(value-1,0,caption.length());
break;
}
case SDLK_RIGHT:
{
value=clamp(value+1,0,caption.length());
break;
}
}
}
}
if(draw){
//Default background opacity
int clr=50;
//If hovering or focused make background more visible.
if(state==1)
clr=128;
else if (state==2)
clr=100;
//Draw the box.
Uint32 color=0xFFFFFF00|clr;
drawGUIBox(x,y,width,height,screen,color);
}
//Get the text.
const char* lp=caption.c_str();
//Make sure it isn't empty.
if(lp!=NULL && lp[0]){
if(!cache){
//Draw the black text.
SDL_Color black={0,0,0,0};
cache=TTF_RenderUTF8_Blended(fontText,lp,black);
}
if(draw){
//Calculate the location, center it vertically.
r.x=x+2;
r.y=y+(height - cache->h)/2;
//Draw the text.
SDL_Rect tmp={0,0,width-2,25};
SDL_BlitSurface(cache,&tmp,screen,&r);
//Only draw the carrot when focus.
if(state==2){
r.x=x;
r.y=y+4;
r.w=2;
r.h=height-8;
int advance;
for(int n=0;n<value;n++){
TTF_GlyphMetrics(fontText,caption[n],NULL,NULL,NULL,NULL,&advance);
r.x+=advance;
}
//Make sure that the carrot is inside the textbox.
if(r.x<x+width)
SDL_FillRect(screen,&r,0);
}
}
}else{
//Only draw the carrot when focus.
if(state==2&&draw){
r.x=x+4;
r.y=y+4;
r.w=2;
r.h=height-8;
SDL_FillRect(screen,&r,0);
}
}
}
break;
case GUIObjectFrame:
{
if(draw){
//Create a rectangle the size of the button and fill it.
Uint32 color=0xDDDDDDFF;
drawGUIBox(x,y,width,height,screen,color);
}
//Get the title text.
const char* lp=caption.c_str();
//Make sure it isn't empty.
if(lp!=NULL && lp[0]){
if(!cache){
cache=TTF_RenderUTF8_Blended(fontGUI,lp,themeTextColorDialog);
}
if(draw){
//Calculate the location, center horizontally and vertically relative to the top.
r.x=x+(width-cache->w)/2;
r.y=y+6-GUI_FONT_RAISE;
//Draw the text and free the surface.
SDL_BlitSurface(cache,NULL,screen,&r);
}
}
}
break;
}
//We now need to draw all the children of the GUIObject.
for(unsigned int i=0;i<childControls.size();i++){
childControls[i]->render(x,y,draw);
}
}
diff --git a/src/InputManager.cpp b/src/InputManager.cpp
index 3878785..3fc0558 100644
--- a/src/InputManager.cpp
+++ b/src/InputManager.cpp
@@ -1,442 +1,432 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "InputManager.h"
#include "Globals.h"
#include "Settings.h"
#include "Functions.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUIOverlay.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
using namespace std;
InputManager inputMgr;
//the order must be the same as InputManagerKeys
static const char* keySettingNames[INPUTMGR_MAX]={
"key_up","key_down","key_left","key_right","key_jump","key_action","key_space","key_cancelRecording",
"key_escape","key_restart","key_tab","key_save","key_load","key_swap",
"key_teleport","key_suicide","key_shift","key_next","key_previous","key_select"
};
//the order must be the same as InputManagerKeys
static const char* keySettingDescription[INPUTMGR_MAX]={
__("Up (in menu)"),__("Down (in menu)"),__("Left"),__("Right"),__("Jump"),__("Action"),__("Space (Record)"),__("Cancel recording"),
__("Escape"),__("Restart"),__("Tab (View shadow/Level prop.)"),__("Save game (in editor)"),__("Load game"),__("Swap (in editor)"),
__("Teleport (in editor)"),__("Suicide (in editor)"),__("Shift (in editor)"),__("Next block type (in Editor)"),
__("Previous block type (in editor)"), __("Select (in menu)")
};
//A class that handles the gui events of the inputDialog.
class InputDialogHandler:public GUIEventCallback{
private:
//the list box which contains keys.
GUIListBox* listBox;
//the parent object.
InputManager* parent;
//check if it's alternative key
bool isAlternativeKey;
//update specified key config item
void updateConfigItem(int index){
//get the description
std::string s=_(keySettingDescription[index]);
s+=": ";
//get key code name
int keyCode=parent->getKeyCode((InputManagerKeys)index,isAlternativeKey);
s+=_(InputManager::getKeyCodeName(keyCode));
//show it
listBox->updateItem(index,s);
}
public:
//Constructor.
InputDialogHandler(GUIListBox* listBox,InputManager* parent):listBox(listBox),parent(parent),isAlternativeKey(false){
//load the available keys to the list box.
for(int i=0;i<INPUTMGR_MAX;i++){
//get the description
std::string s=_(keySettingDescription[i]);
s+=": ";
//get key code name
int keyCode=parent->getKeyCode((InputManagerKeys)i,false);
s+=_(InputManager::getKeyCodeName(keyCode));
//add item
listBox->addItem(s);
}
}
//when a key is pressed call this to set the key to currently-selected item
void onKeyDown(int keyCode){
//check if an item is selected.
int index=listBox->value;
if(index<0 || index>=INPUTMGR_MAX) return;
//set it.
parent->setKeyCode((InputManagerKeys)index,keyCode,isAlternativeKey);
updateConfigItem(index);
}
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Make sure it's a click event.
if(eventType==GUIEventClick){
- if(name=="cmdOK"){
- //config is done, exiting
- delete GUIObjectRoot;
- GUIObjectRoot=NULL;
- }else if(name=="cmdUnset"){
+ if(name=="cmdUnset"){
onKeyDown(0);
}else if(name=="lstType"){
isAlternativeKey=(obj->value==1);
for(int i=0;i<INPUTMGR_MAX;i++){
updateConfigItem(i);
}
}
}
}
};
//Event handler.
static InputDialogHandler* handler;
//A GUIObject that is used to create events for key presses.
class GUIKeyListener:public GUIObject{
//Leave empty.
~GUIKeyListener(){}
bool handleEvents(int x,int y,bool enabled,bool visible,bool processed){
if(enabled && handler){
if(event.type==SDL_KEYDOWN){
handler->onKeyDown(event.key.keysym.sym);
}
//Joystick
else if(event.type==SDL_JOYAXISMOTION){
if(event.jaxis.value>3200){
handler->onKeyDown(0x00010001 | (int(event.jaxis.axis)<<8));
}else if(event.jaxis.value<-3200){
handler->onKeyDown(0x000100FF | (int(event.jaxis.axis)<<8));
}
}
else if(event.type==SDL_JOYBUTTONDOWN){
handler->onKeyDown(0x00020000 | (int(event.jbutton.button)<<8));
}
else if(event.type==SDL_JOYHATMOTION){
if(event.jhat.value & SDL_HAT_LEFT){
handler->onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_LEFT);
}else if(event.jhat.value & SDL_HAT_RIGHT){
handler->onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_RIGHT);
}else if(event.jhat.value & SDL_HAT_UP){
handler->onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_UP);
}else if(event.jhat.value & SDL_HAT_DOWN){
handler->onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_DOWN);
}
}
}
- //Return true?
- return true;
+ return false;
}
//Nothing to do.
void render(){}
};
int InputManager::getKeyCode(InputManagerKeys key,bool isAlternativeKey){
if(isAlternativeKey) return alternativeKeys[key];
else return keys[key];
}
void InputManager::setKeyCode(InputManagerKeys key,int keyCode,bool isAlternativeKey){
if(isAlternativeKey) alternativeKeys[key]=keyCode;
else keys[key]=keyCode;
}
void InputManager::loadConfig(){
int i;
for(i=0;i<INPUTMGR_MAX;i++){
string s=keySettingNames[i];
keys[i]=atoi(getSettings()->getValue(s).c_str());
s+="2";
alternativeKeys[i]=atoi(getSettings()->getValue(s).c_str());
}
}
void InputManager::saveConfig(){
int i;
char c[32];
for(i=0;i<INPUTMGR_MAX;i++){
string s=keySettingNames[i];
sprintf(c,"%d",keys[i]);
getSettings()->setValue(s,c);
s+="2";
sprintf(c,"%d",alternativeKeys[i]);
getSettings()->setValue(s,c);
}
}
-void InputManager::showConfig(){
+GUIObject* InputManager::showConfig(int height){
//Create the new GUI.
- GUIObject* root=new GUIObject((SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-420)/2,600,400,GUIObjectFrame,_("Config Keys"));
- GUIObject* obj;
+ GUIObject* root=new GUIObject(0,0,SCREEN_WIDTH,height,GUIObjectNone);
- obj=new GUIObject(0,44,root->width,36,GUIObjectLabel,_("Select an item and press a key to config it."),0,true,true,GUIGravityCenter);
+ //Instruction label.
+ GUIObject* obj=new GUIObject(0,0,root->width,36,GUIObjectLabel,_("Select an item and press a key to config it."),0,true,true,GUIGravityCenter);
root->addChild(obj);
-
- //The list box.
- GUIListBox *listBox=new GUIListBox(20,126,560,220);
+
+ //The listbox for keys.
+ GUIListBox *listBox=new GUIListBox(SCREEN_WIDTH*0.15,72,SCREEN_WIDTH*0.7,height-36-72-8);
+ root->addChild(listBox);
+
//Create the event handler.
if(handler)
delete handler;
handler=new InputDialogHandler(listBox,this);
- root->addChild(listBox);
-
- //another box to select key type
- GUISingleLineListBox *listBox0=new GUISingleLineListBox(120,80,360,36);
+
+ //Listbox for selection between primary and alternative keys.
+ GUISingleLineListBox *listBox0=new GUISingleLineListBox(SCREEN_WIDTH/2,32,360,36,true,true,GUIGravityCenter);
listBox0->name="lstType";
listBox0->item.push_back(_("Primary key"));
listBox0->item.push_back(_("Alternative key"));
listBox0->value=0;
listBox0->eventCallback=handler;
root->addChild(listBox0);
- //two buttons
- obj=new GUIObject(32,360,-1,36,GUIObjectButton,_("Unset the key"),0,true,true,GUIGravityLeft);
+ //Button to unset selected key in the listbox.
+ obj=new GUIObject(root->width/2,height-36,-1,36,GUIObjectButton,_("Unset the key"),0,true,true,GUIGravityCenter);
obj->name="cmdUnset";
obj->eventCallback=handler;
root->addChild(obj);
- obj=new GUIObject(root->width-32,360,-1,36,GUIObjectButton,_("OK"),0,true,true,GUIGravityRight);
- obj->name="cmdOK";
- obj->eventCallback=handler;
- root->addChild(obj);
-
obj=new GUIKeyListener();
root->addChild(obj);
- //Create a GUIOverlayState
- //NOTE: We don't need to store a pointer since it will auto cleanup itself.
- new GUIOverlay(root,true);
+ //Return final widget.
+ return root;
}
//get key name from key code
std::string InputManager::getKeyCodeName(int keyCode){
char c[64];
if(keyCode>0 && keyCode <0x1000){
//keyboard
char* s=SDL_GetKeyName((SDLKey)keyCode);
if(s!=NULL){
return s;
}else{
sprintf(c,"(Key %d)",keyCode);
return c;
}
}else if(keyCode>0x1000){
//Joystick. first set it to invalid value
sprintf(c,"(Joystick 0x%08X)",keyCode);
//check type
switch((keyCode & 0x00FF0000)>>16){
case 1:
//axis
switch(keyCode & 0xFF){
case 1:
sprintf(c,"Joystick axis %d +",(keyCode & 0x0000FF00)>>8);
break;
case 0xFF:
sprintf(c,"Joystick axis %d -",(keyCode & 0x0000FF00)>>8);
break;
}
break;
case 2:
//button
sprintf(c,"Joystick button %d",(keyCode & 0x0000FF00)>>8);
break;
case 3:
//hat
switch(keyCode & 0xFF){
case SDL_HAT_LEFT:
sprintf(c,"Joystick hat %d left",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_RIGHT:
sprintf(c,"Joystick hat %d right",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_UP:
sprintf(c,"Joystick hat %d up",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_DOWN:
sprintf(c,"Joystick hat %d down",(keyCode & 0x0000FF00)>>8);
break;
}
break;
}
return c;
}else{
//unknown??
return _("(Not set)");
}
}
InputManager::InputManager(){
//clear the array.
for(int i=0;i<INPUTMGR_MAX;i++){
keys[i]=alternativeKeys[i]=keyFlags[i]=0;
}
}
InputManager::~InputManager(){
closeAllJoysticks();
}
int InputManager::getKeyState(int keyCode,int oldState,bool hasEvent){
int state=0;
if(keyCode>0 && keyCode<0x1000){
//keyboard
if(hasEvent){
if(event.type==SDL_KEYDOWN && event.key.keysym.sym==keyCode){
state|=0x2;
}
if(event.type==SDL_KEYUP && event.key.keysym.sym==keyCode){
state|=0x4;
}
}
if(keyCode<SDLK_LAST && SDL_GetKeyState(NULL)[keyCode]){
state|=0x1;
}
}else if(keyCode>0x1000){
//Joystick
int index=(keyCode & 0x0000FF00)>>8;
int value=keyCode & 0xFF;
int i,v;
switch((keyCode & 0x00FF0000)>>16){
case 1:
//axis
if(hasEvent){
if(event.type==SDL_JOYAXISMOTION && event.jaxis.axis==index){
if((value==1 && event.jaxis.value>3200) || (value==0xFF && event.jaxis.value<-3200)){
if((oldState & 0x1)==0) state|=0x2;
}else{
if(oldState & 0x1) state|=0x4;
}
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetAxis(joysticks[i],index);
if((value==1 && v>3200) || (value==0xFF && v<-3200)){
state|=0x1;
break;
}
}
break;
case 2:
//button
if(hasEvent){
if(event.type==SDL_JOYBUTTONDOWN && event.jbutton.button==index){
state|=0x2;
}
if(event.type==SDL_JOYBUTTONUP && event.jbutton.button==index){
state|=0x4;
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetButton(joysticks[i],index);
if(v){
state|=0x1;
break;
}
}
break;
case 3:
//hat
if(hasEvent){
if(event.type==SDL_JOYHATMOTION && event.jhat.hat==index){
if(event.jhat.value & value){
if((oldState & 0x1)==0) state|=0x2;
}else{
if(oldState & 0x1) state|=0x4;
}
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetHat(joysticks[i],index);
if(v & value){
state|=0x1;
break;
}
}
break;
}
}
return state;
}
//update the key state, according to current SDL event, etc.
void InputManager::updateState(bool hasEvent){
for(int i=0;i<INPUTMGR_MAX;i++){
keyFlags[i]=getKeyState(keys[i],keyFlags[i],hasEvent)|getKeyState(alternativeKeys[i],keyFlags[i],hasEvent);
}
}
//check if there is KeyDown event.
bool InputManager::isKeyDownEvent(InputManagerKeys key){
return keyFlags[key]&0x2;
}
//check if there is KeyUp event.
bool InputManager::isKeyUpEvent(InputManagerKeys key){
return keyFlags[key]&0x4;
}
//check if specified key is down.
bool InputManager::isKeyDown(InputManagerKeys key){
return keyFlags[key]&0x1;
}
//open all joysticks.
void InputManager::openAllJoysitcks(){
int i,m;
//First close previous joysticks.
closeAllJoysticks();
//open all joysticks.
m=SDL_NumJoysticks();
for(i=0;i<m;i++){
SDL_Joystick *j=SDL_JoystickOpen(i);
if(j==NULL){
printf("ERROR: Couldn't open Joystick %d\n",i);
}else{
joysticks.push_back(j);
}
}
}
//close all joysticks.
void InputManager::closeAllJoysticks(){
for(int i=0;i<(int)joysticks.size();i++){
SDL_JoystickClose(joysticks[i]);
}
joysticks.clear();
}
diff --git a/src/InputManager.h b/src/InputManager.h
index 1b6b1cf..013882e 100644
--- a/src/InputManager.h
+++ b/src/InputManager.h
@@ -1,113 +1,115 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INPUTMANAGER_H
#define INPUTMANAGER_H
#include <SDL/SDL.h>
#include <vector>
#include <string>
+#include "GUIObject.h"
+
enum InputManagerKeys{
INPUTMGR_UP,
INPUTMGR_DOWN,
INPUTMGR_LEFT,
INPUTMGR_RIGHT,
INPUTMGR_JUMP,
INPUTMGR_ACTION,
INPUTMGR_SPACE,
INPUTMGR_CANCELRECORDING,
INPUTMGR_ESCAPE,
INPUTMGR_RESTART,
INPUTMGR_TAB,
INPUTMGR_SAVE,
INPUTMGR_LOAD,
INPUTMGR_SWAP,
INPUTMGR_TELEPORT,
INPUTMGR_SUICIDE,
INPUTMGR_SHIFT,
INPUTMGR_NEXT,
INPUTMGR_PREVIOUS,
INPUTMGR_SELECT,
INPUTMGR_MAX
};
class InputManager{
public:
InputManager();
~InputManager();
//Get and set key code of each key.
int getKeyCode(InputManagerKeys key,bool isAlternativeKey);
void setKeyCode(InputManagerKeys key,int keyCode,bool isAlternativeKey);
//Load and save key settings from config file.
void loadConfig();
void saveConfig();
//Show the config screen.
- void showConfig();
+ GUIObject* showConfig(int height);
//Get key name from key code
static std::string getKeyCodeName(int keyCode);
//Update the key state, according to current SDL event, etc.
void updateState(bool hasEvent);
//Check if there is KeyDown event.
bool isKeyDownEvent(InputManagerKeys key);
//Check if there is KeyUp event.
bool isKeyUpEvent(InputManagerKeys key);
//Check if specified key is down.
bool isKeyDown(InputManagerKeys key);
//Open all joysticks.
void openAllJoysitcks();
//Close all joysticks.
void closeAllJoysticks();
private:
//the key code of each key.
// - note of key code:
// 0 means this key is disabled (??)
// 1 to 4095 (0xFFF) means keyboard keys,
// currently SDLKey is less than 4095
// >= 4096: bit field value means joystick.
// 0xWWXXYYZZ
// WW = joystick index. currently unused, should be 0.
// XX = joystick button type: 1-axis 2-button 3-hat, currently ball is unsupported
// YY = joystick button index. (we assume joystick has at most 256 buttons)
// ZZ = value. if type=axis then value should be 1 or 0xFF.
// if type=button then it's unused.
// if type=hat then it's SDL_HAT_LEFT, SDL_HAT_RIGHT, SDL_HAT_UP or SDL_HAT_DOWN.
int keys[INPUTMGR_MAX];
int alternativeKeys[INPUTMGR_MAX];
//the bit-field flag array saves the key states.
// 0x1 means the key is down.
// 0x2 means KeyDown event.
// 0x4 means KeyUp event.
int keyFlags[INPUTMGR_MAX];
//contains all joysticks.
std::vector<SDL_Joystick*> joysticks;
//internal function
int getKeyState(int keyCode,int oldState,bool hasEvent);
};
extern InputManager inputMgr;
#endif //INPUTMANAGER_H
diff --git a/src/TitleMenu.cpp b/src/TitleMenu.cpp
index 9b8087d..7e4616e 100644
--- a/src/TitleMenu.cpp
+++ b/src/TitleMenu.cpp
@@ -1,837 +1,876 @@
/*
* Copyright (C) 2011-2013 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Functions.h"
#include "GameState.h"
#include "Globals.h"
#include "TitleMenu.h"
#include "GUIListBox.h"
#include "GUITextArea.h"
#include "InputManager.h"
#include "StatisticsManager.h"
#include <iostream>
#include <algorithm>
#include <sstream>
#include "libs/tinygettext/tinygettext.hpp"
using namespace std;
/////////////////////////MAIN_MENU//////////////////////////////////
//Integer containing the highlighted/selected menu option.
static int highlight=0;
Menu::Menu(){
highlight=0;
animation=0;
//Load the title image.
title=loadImage(getDataPath()+"gfx/menu/title.png");
//Now render the five entries.
//SDL_Color black={0,0,0};
entries[0]=TTF_RenderUTF8_Blended(fontTitle,_("Play"),themeTextColor);
entries[1]=TTF_RenderUTF8_Blended(fontTitle,_("Options"),themeTextColor);
entries[2]=TTF_RenderUTF8_Blended(fontTitle,_("Map Editor"),themeTextColor);
entries[3]=TTF_RenderUTF8_Blended(fontTitle,_("Addons"),themeTextColor);
entries[4]=TTF_RenderUTF8_Blended(fontTitle,_("Quit"),themeTextColor);
entries[5]=TTF_RenderUTF8_Blended(fontTitle,">",themeTextColor);
entries[6]=TTF_RenderUTF8_Blended(fontTitle,"<",themeTextColor);
//Load the credits icon.
creditsIcon=loadImage(getDataPath()+"gfx/menu/credits.png");
statisticsIcon=loadImage(getDataPath()+"gfx/menu/statistics.png");
}
Menu::~Menu(){
//We need to free the five text surfaceses.
for(unsigned int i=0;i<7;i++)
SDL_FreeSurface(entries[i]);
}
void Menu::handleEvents(){
//Get the x and y location of the mouse.
int x,y;
SDL_GetMouseState(&x,&y);
//Calculate which option is highlighted using the location of the mouse.
//Only if mouse is 'doing something'
if(event.type==SDL_MOUSEMOTION || event.type==SDL_MOUSEBUTTONDOWN){
highlight=0;
if(x>=200&&x<SCREEN_WIDTH-200&&y>=(SCREEN_HEIGHT-250)/2&&y<(SCREEN_HEIGHT-200)/2+320){
highlight=(y-((SCREEN_HEIGHT-200)/2-64))/64;
if(highlight>5) highlight=0;
}
//Also check the icons.
if(y>=SCREEN_HEIGHT-56&&y<SCREEN_HEIGHT-8){
if(x>=SCREEN_WIDTH-8){
//do nothing
}else if(x>=SCREEN_WIDTH-56){
highlight=7;
}else if(x>=SCREEN_WIDTH-104){
highlight=6;
}
}
}
//Down/Up -arrows move highlight
if(inputMgr.isKeyDownEvent(INPUTMGR_DOWN)){
highlight++;
if(highlight>7)
highlight=0;
}
if(inputMgr.isKeyDownEvent(INPUTMGR_UP)){
highlight--;
if(highlight<1)
highlight=7;
}
//Check if there's a press event.
if((event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT) ||
(inputMgr.isKeyUpEvent(INPUTMGR_SELECT))){
//We have one so check which selected/highlighted option needs to be done.
switch(highlight){
case 1:
//Enter the levelSelect state.
setNextState(STATE_LEVEL_SELECT);
break;
case 2:
//Enter the options state.
setNextState(STATE_OPTIONS);
break;
case 3:
//Enter the levelEditor, but first set the level to a default leveledit map.
levelName="";
setNextState(STATE_LEVEL_EDIT_SELECT);
break;
case 4:
//Check if internet is enabled.
if(!getSettings()->getBoolValue("internet")){
msgBox(_("Enable internet in order to install addons."),MsgBoxOKOnly,_("Internet disabled"));
break;
}
//Enter the addons state.
setNextState(STATE_ADDONS);
break;
case 5:
//We quit, so we enter the exit state.
setNextState(STATE_EXIT);
break;
case 6:
//Show the credits screen.
setNextState(STATE_CREDITS);
break;
case 7:
//Show the statistics screen.
setNextState(STATE_STATISTICS);
break;
}
}
//We also need to quit the menu when escape is pressed.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_EXIT);
}
//Check if we need to quit, if so we enter the exit state.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
}
//Nothing to do here
void Menu::logic(){
animation++;
if(animation>10)
animation=-10;
}
void Menu::render(){
//Draw background.
objThemes.getBackground(true)->draw(screen);
objThemes.getBackground(true)->updateAnimation();
//Draw the title.
applySurface((SCREEN_WIDTH-title->w)/2,40,title,screen,NULL);
//Draw the menu entries.
for(unsigned int i=0;i<5;i++){
applySurface((SCREEN_WIDTH-entries[i]->w)/2,(SCREEN_HEIGHT-200)/2+64*i+(64-entries[i]->h)/2,entries[i],screen,NULL);
}
//Check if an option is selected/highlighted.
if(highlight>0 && highlight<=5){
//Draw the '>' sign, which is entry 5.
int x=(SCREEN_WIDTH-entries[highlight-1]->w)/2-(25-abs(animation)/2)-entries[5]->w;
int y=(SCREEN_HEIGHT-200)/2-64+64*highlight+(64-entries[5]->h)/2;
applySurface(x,y,entries[5],screen,NULL);
//Draw the '<' sign, which is entry 6.
x=(SCREEN_WIDTH-entries[highlight-1]->w)/2+entries[highlight-1]->w+(25-abs(animation)/2);
y=(SCREEN_HEIGHT-200)/2-64+64*highlight+(64-entries[6]->h)/2;
applySurface(x,y,entries[6],screen,NULL);
}
//Check if an icon is selected/highlighted and draw tooltip
if(highlight==6 || highlight==7){
SDL_Color fg={0,0,0};
SDL_Surface *surface=NULL;
if(highlight==6)
surface=TTF_RenderUTF8_Blended(fontText,_("Credits"),fg);
else
surface=TTF_RenderUTF8_Blended(fontText,_("Achievements and Statistics"),fg);
drawGUIBox(-2,SCREEN_HEIGHT-surface->h-2,surface->w+4,surface->h+4,screen,0xFFFFFFFF);
applySurface(0,SCREEN_HEIGHT-surface->h,surface,screen,NULL);
SDL_FreeSurface(surface);
}
- //Draw the credits icon.
+ //Draw icons.
applySurface(SCREEN_WIDTH-96,SCREEN_HEIGHT-48,creditsIcon,screen,NULL);
applySurface(SCREEN_WIDTH-48,SCREEN_HEIGHT-48,statisticsIcon,screen,NULL);
}
void Menu::resize(){}
/////////////////////////OPTIONS_MENU//////////////////////////////////
//Some varables for the options.
static bool fullscreen,leveltheme,internet;
static string themeName,languageName;
static int lastLang,lastRes;
static bool useProxy;
static string internetProxy;
static bool restartFlag;
static _res currentRes;
static vector<_res> resolutionList;
Options::Options(){
//Render the title.
title=TTF_RenderUTF8_Blended(fontTitle,_("Settings"),themeTextColor);
+ //Initialize variables.
lastJumpSound=0;
+ clearIconHower=false;
+
+ //Load icon image.
+ clearIcon=loadImage(getDataPath()+"gfx/menu/clear-progress.png");
//Set some default settings.
fullscreen=getSettings()->getBoolValue("fullscreen");
languageName=getSettings()->getValue("lang");
themeName=processFileName(getSettings()->getValue("theme"));
leveltheme=getSettings()->getBoolValue("leveltheme");
internet=getSettings()->getBoolValue("internet");
internetProxy=getSettings()->getValue("internet-proxy");
useProxy=!internetProxy.empty();
//Set the restartFlag false.
restartFlag=false;
//Now create the gui.
createGUI();
}
Options::~Options(){
//Delete the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Free the title image.
SDL_FreeSurface(title);
}
void Options::createGUI(){
- //Variables for positioning
- int x = (SCREEN_WIDTH-540)/2;
- int liftY=40; //TODO: This is variable for laziness of maths...
+ //Variables for positioning
+ const int columnW=SCREEN_WIDTH*0.3;
+ const int column1X=SCREEN_WIDTH*0.15;
+ const int column2X=SCREEN_WIDTH*0.55;
+ const int lineHeight=40;
//Create the root element of the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,GUIObjectNone);
-
+
+ //Single line list for different tabs.
+ GUISingleLineListBox* listBox=new GUISingleLineListBox((SCREEN_WIDTH-500)/2,104,500,32);
+ listBox->item.push_back(_("General"));
+ listBox->item.push_back(_("Controls"));
+ listBox->value=0;
+ listBox->name="lstTabs";
+ listBox->eventCallback=this;
+ GUIObjectRoot->addChild(listBox);
+
+ //Create general tab.
+ tabGeneral=new GUIObject(0,150,SCREEN_WIDTH,SCREEN_HEIGHT,GUIObjectNone);
+ GUIObjectRoot->addChild(tabGeneral);
+
//Now we create GUIObjects for every option.
- GUIObject* obj=new GUIObject(x,150-liftY,240,36,GUIObjectLabel,_("Music"));
- GUIObjectRoot->addChild(obj);
+ GUIObject* obj=new GUIObject(column1X,0,columnW,36,GUIObjectLabel,_("Music"));
+ tabGeneral->addChild(obj);
- musicSlider=new GUISlider(x+220,150-liftY,256,36,atoi(getSettings()->getValue("music").c_str()),0,128,15);
+ musicSlider=new GUISlider(column2X,0,columnW,36,atoi(getSettings()->getValue("music").c_str()),0,128,15);
musicSlider->name="sldMusic";
musicSlider->eventCallback=this;
- GUIObjectRoot->addChild(musicSlider);
+ tabGeneral->addChild(musicSlider);
- obj=new GUIObject(x,190-liftY,240,36,GUIObjectLabel,_("Sound"));
- GUIObjectRoot->addChild(obj);
+ obj=new GUIObject(column1X,lineHeight,columnW,36,GUIObjectLabel,_("Sound"));
+ tabGeneral->addChild(obj);
- soundSlider=new GUISlider(x+220,190-liftY,256,36,atoi(getSettings()->getValue("sound").c_str()),0,128,15);
+ soundSlider=new GUISlider(column2X,lineHeight,columnW,36,atoi(getSettings()->getValue("sound").c_str()),0,128,15);
soundSlider->name="sldSound";
soundSlider->eventCallback=this;
- GUIObjectRoot->addChild(soundSlider);
-
- obj=new GUIObject(x,230-liftY,240,36,GUIObjectCheckBox,_("Fullscreen"),fullscreen?1:0);
- obj->name="chkFullscreen";
- obj->eventCallback=this;
- GUIObjectRoot->addChild(obj);
+ tabGeneral->addChild(soundSlider);
- obj=new GUIObject(x,270-liftY,240,36,GUIObjectLabel,_("Resolution"));
+ obj=new GUIObject(column1X,2*lineHeight,columnW,36,GUIObjectLabel,_("Resolution"));
obj->name="lstResolution";
- GUIObjectRoot->addChild(obj);
+ tabGeneral->addChild(obj);
- //Create list with many different resolutions
- resolutions = new GUISingleLineListBox(x+220,270-liftY,300,36);
+ //Create list with many different resolutions.
+ resolutions = new GUISingleLineListBox(column2X,2*lineHeight,columnW,36);
resolutions->value=-1;
//Enumerate available resolutions using SDL_ListModes()
//Note: we enumerate fullscreen resolutions because
- // windowed resolutions always can be arbitrary
+ // windowed resolutions always can be arbitrary.
if(resolutionList.empty()){
SDL_Rect **modes=SDL_ListModes(NULL,SDL_FULLSCREEN|SDL_HWSURFACE);
if(modes==NULL || ((intptr_t)modes) == -1){
cout<<"Error: Can't enumerate available screen resolutions."
" Use predefined screen resolutions list instead."<<endl;
static const _res predefinedResolutionList[] = {
{800,600},
{1024,600},
{1024,768},
{1152,864},
{1280,720},
{1280,768},
{1280,800},
{1280,960},
{1280,1024},
{1360,768},
{1366,768},
{1440,900},
{1600,900},
{1600,1200},
{1680,1080},
{1920,1080},
{1920,1200},
{2560,1440},
{3840,2160}
};
for(unsigned int i=0;i<sizeof(predefinedResolutionList)/sizeof(_res);i++){
resolutionList.push_back(predefinedResolutionList[i]);
}
}else{
for(unsigned int i=0;modes[i]!=NULL;i++){
//Check if the resolution is big enough
if(modes[i]->w>=800 && modes[i]->h>=600){
_res res={modes[i]->w, modes[i]->h};
resolutionList.push_back(res);
}
}
reverse(resolutionList.begin(),resolutionList.end());
}
}
- //Get current resolution from config file. Thus it can be user defined
+ //Get current resolution from config file. Thus it can be user defined.
currentRes.w=atoi(getSettings()->getValue("width").c_str());
currentRes.h=atoi(getSettings()->getValue("height").c_str());
for (int i=0; i<(int)resolutionList.size();i++){
- //Create a string from width and height and then add it to list
+ //Create a string from width and height and then add it to list.
ostringstream out;
out << resolutionList[i].w << "x" << resolutionList[i].h;
resolutions->item.push_back(out.str());
- //Check if current resolution matches, select it
+ //Check if current resolution matches, select it.
if (resolutionList[i].w==currentRes.w && resolutionList[i].h==currentRes.h){
resolutions->value=i;
}
}
- //Add current resolution if it isn't already in the list
+ //Add current resolution if it isn't already in the list.
if(resolutions->value==-1){
ostringstream out;
out << currentRes.w << "x" << currentRes.h;
resolutions->item.push_back(out.str());
resolutions->value=resolutions->item.size()-1;
}
lastRes=resolutions->value;
- GUIObjectRoot->addChild(resolutions);
+ tabGeneral->addChild(resolutions);
- obj=new GUIObject(x,310-liftY,240,36,GUIObjectLabel,_("Language"));
- obj->name="lstResolution";
- GUIObjectRoot->addChild(obj);
+ obj=new GUIObject(column1X,3*lineHeight,columnW,36,GUIObjectLabel,_("Language"));
+ tabGeneral->addChild(obj);
- //Create GUI list with available languages
- langs = new GUISingleLineListBox(x+220,310-liftY,300,36);
+ //Create GUI list with available languages.
+ langs = new GUISingleLineListBox(column2X,3*lineHeight,columnW,36);
langs->name="lstLanguages";
/// TRANSLATORS: as detect user's language automatically
langs->item.push_back(_("Auto-Detect"));
langValues.push_back("");
langs->item.push_back("English");
langValues.push_back("en");
- //Get a list of every available language
+ //Get a list of every available language.
set<tinygettext::Language> languages = dictionaryManager->get_languages();
for (set<tinygettext::Language>::iterator s0 = languages.begin(); s0 != languages.end(); ++s0){
//If language in loop is the same in config file, then select it
if(getSettings()->getValue("lang")==s0->str()){
lastLang=distance(languages.begin(),s0)+2;
}
- //Add language in loop to list and listbox
+ //Add language in loop to list and listbox.
langs->item.push_back(s0->get_name());
langValues.push_back(s0->str());
}
- //If Auto or English are selected
+ //If Auto or English are selected.
if(getSettings()->getValue("lang")==""){
lastLang=0;
}else if(getSettings()->getValue("lang")=="en"){
lastLang=1;
}
langs->value=lastLang;
- GUIObjectRoot->addChild(langs);
+ tabGeneral->addChild(langs);
- obj=new GUIObject(x,350-liftY,240,36,GUIObjectLabel,_("Theme"));
+ obj=new GUIObject(column1X,4*lineHeight,columnW,36,GUIObjectLabel,_("Theme"));
obj->name="theme";
- GUIObjectRoot->addChild(obj);
+ tabGeneral->addChild(obj);
//Create the theme option gui element.
- theme=new GUISingleLineListBox(x+220,350-liftY,300,36);
+ theme=new GUISingleLineListBox(column2X,4*lineHeight,columnW,36);
theme->name="lstTheme";
vector<string> v=enumAllDirs(getUserPath(USER_DATA)+"themes/");
for(vector<string>::iterator i = v.begin(); i != v.end(); ++i){
themeLocations[*i]=getUserPath(USER_DATA)+"themes/"+*i;
}
vector<string> v2=enumAllDirs(getDataPath()+"themes/");
for(vector<string>::iterator i = v2.begin(); i != v2.end(); ++i){
themeLocations[*i]=getDataPath()+"themes/"+*i;
}
v.insert(v.end(), v2.begin(), v2.end());
//Try to find the configured theme so we can display it.
int value=-1;
for(vector<string>::iterator i = v.begin(); i != v.end(); ++i){
if(themeLocations[*i]==themeName) {
value=i-v.begin();
}
}
theme->item=v;
if(value==-1)
value=theme->item.size()-1;
theme->value=value;
//NOTE: We call the event handling method to correctly set the themename.
GUIEventCallback_OnEvent("lstTheme",theme,GUIEventChange);
theme->eventCallback=this;
- GUIObjectRoot->addChild(theme);
+ tabGeneral->addChild(theme);
- obj=new GUIObject(x,390-liftY,240,36,GUIObjectCheckBox,_("Level themes"),leveltheme?1:0);
- obj->name="chkLeveltheme";
+ //Proxy settings.
+ obj=new GUIObject(column1X,5*lineHeight,columnW,36,GUIObjectLabel,_("Internet proxy"));
+ obj->name="chkProxy";
+ obj->eventCallback=this;
+ tabGeneral->addChild(obj);
+ obj=new GUIObject(column2X,5*lineHeight,columnW,36,GUIObjectTextBox,internetProxy.c_str());
+ obj->name="txtProxy";
obj->eventCallback=this;
- GUIObjectRoot->addChild(obj);
+ tabGeneral->addChild(obj);
- obj=new GUIObject(x,430-liftY,240,36,GUIObjectCheckBox,_("Internet"),internet?1:0);
- obj->name="chkInternet";
+ obj=new GUIObject(column1X,6*lineHeight,columnW,36,GUIObjectCheckBox,_("Fullscreen"),fullscreen?1:0);
+ obj->name="chkFullscreen";
obj->eventCallback=this;
- GUIObjectRoot->addChild(obj);
-
- //new: proxy settings
- obj=new GUIObject(x,470-liftY,240,36,GUIObjectLabel,_("Internet proxy"));
- obj->name="chkProxy";
+ tabGeneral->addChild(obj);
+
+ obj=new GUIObject(column1X,7*lineHeight,columnW,36,GUIObjectCheckBox,_("Level themes"),leveltheme?1:0);
+ obj->name="chkLeveltheme";
obj->eventCallback=this;
- GUIObjectRoot->addChild(obj);
- obj=new GUIObject(x+220,470-liftY,300,36,GUIObjectTextBox,internetProxy.c_str());
- obj->name="txtProxy";
+ tabGeneral->addChild(obj);
+
+ obj=new GUIObject(column2X,6*lineHeight,columnW,36,GUIObjectCheckBox,_("Internet"),internet?1:0);
+ obj->name="chkInternet";
obj->eventCallback=this;
- GUIObjectRoot->addChild(obj);
-
- //new: key settings
- GUIObject* b1=new GUIObject(SCREEN_WIDTH*0.3,SCREEN_HEIGHT-120,-1,36,GUIObjectButton,_("Config Keys"),0,true,true,GUIGravityCenter);
- b1->name="cmdKeys";
- b1->eventCallback=this;
- GUIObjectRoot->addChild(b1);
+ tabGeneral->addChild(obj);
- //Reset progress settings.
- /// TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
- GUIObject* b2=new GUIObject(SCREEN_WIDTH*0.7,SCREEN_HEIGHT-120,-1,36,GUIObjectButton,_("Clear Progress"),0,true,true,GUIGravityCenter);
- b2->name="cmdReset";
- b2->eventCallback=this;
- GUIObjectRoot->addChild(b2);
+ //Create the controls tab.
+ tabControls=inputMgr.showConfig(SCREEN_HEIGHT-210);
+ tabControls->top=140;
+ tabControls->visible=false;
+ GUIObjectRoot->addChild(tabControls);
- b1->render(0,0,false);
- b2->render(0,0,false);
- if(b2->left-b2->gravityX < b1->left+b1->width-b1->gravityX){
- b1->smallFont=true;
- b1->width=-1;
- b2->smallFont=true;
- b2->width=-1;
+ //Save original keys.
+ for(int i=0;i<INPUTMGR_MAX;i++){
+ tmpKeys[i]=inputMgr.getKeyCode((InputManagerKeys)i,false);
+ tmpAlternativeKeys[i]=inputMgr.getKeyCode((InputManagerKeys)i,true);
}
-
- b1=new GUIObject(SCREEN_WIDTH*0.3,SCREEN_HEIGHT-60,-1,36,GUIObjectButton,_("Cancel"),0,true,true,GUIGravityCenter);
+
+ //Create buttons.
+ GUIObject*b1=new GUIObject(SCREEN_WIDTH*0.3,SCREEN_HEIGHT-60,-1,36,GUIObjectButton,_("Cancel"),0,true,true,GUIGravityCenter);
b1->name="cmdBack";
b1->eventCallback=this;
GUIObjectRoot->addChild(b1);
- b2=new GUIObject(SCREEN_WIDTH*0.7,SCREEN_HEIGHT-60,-1,36,GUIObjectButton,_("Save Changes"),0,true,true,GUIGravityCenter);
+ GUIObject* b2=new GUIObject(SCREEN_WIDTH*0.7,SCREEN_HEIGHT-60,-1,36,GUIObjectButton,_("Save Changes"),0,true,true,GUIGravityCenter);
b2->name="cmdSave";
b2->eventCallback=this;
GUIObjectRoot->addChild(b2);
-
- b1->render(0,0,false);
- b2->render(0,0,false);
- if(b2->left-b2->gravityX < b1->left+b1->width-b1->gravityX){
- b1->smallFont=true;
- b1->width=-1;
- b2->smallFont=true;
- b2->width=-1;
- }
}
static string convertInt(int i){
stringstream ss;
ss << i;
return ss.str();
}
void Options::GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Check what type of event it was.
if(eventType==GUIEventClick){
if(name=="cmdBack"){
- //TODO: Reset the key changes.
+ //Reset the key changes.
+ for(int i=0;i<INPUTMGR_MAX;i++){
+ inputMgr.setKeyCode((InputManagerKeys)i,tmpKeys[i],false);
+ inputMgr.setKeyCode((InputManagerKeys)i,tmpAlternativeKeys[i],true);
+ }
//Reset the music volume.
getMusicManager()->setVolume(atoi(getSettings()->getValue("music").c_str()));
Mix_Volume(-1,atoi(getSettings()->getValue("sound").c_str()));
//And goto the main menu.
setNextState(STATE_MENU);
}else if(name=="cmdSave"){
//Save is pressed thus save
char s[64];
sprintf(s,"%d",soundSlider->value);
getSettings()->setValue("sound",s);
sprintf(s,"%d",musicSlider->value);
getSettings()->setValue("music",s);
getMusicManager()->setEnabled(musicSlider->value>0);
Mix_Volume(-1,soundSlider->value);
getSettings()->setValue("fullscreen",fullscreen?"1":"0");
getSettings()->setValue("leveltheme",leveltheme?"1":"0");
getSettings()->setValue("internet",internet?"1":"0");
getSettings()->setValue("theme",themeName);
//Before loading the theme remove the previous one from the stack.
objThemes.removeTheme();
loadTheme(themeName);
if(!useProxy)
internetProxy.clear();
getSettings()->setValue("internet-proxy",internetProxy);
getSettings()->setValue("lang",langValues.at(langs->value));
//Is resolution from the list or is it user defined in config file
if(resolutions->value<(int)resolutionList.size()){
getSettings()->setValue("width",convertInt(resolutionList[resolutions->value].w));
getSettings()->setValue("height",convertInt(resolutionList[resolutions->value].h));
}else{
getSettings()->setValue("width",convertInt(currentRes.w));
getSettings()->setValue("height",convertInt(currentRes.h));
}
//Save the key configuration.
inputMgr.saveConfig();
//Save the settings.
saveSettings();
//Before we return check if some .
if(restartFlag || resolutions->value!=lastRes){
//The resolution changed so we need to recreate the screen.
if(!createScreen()){
//Screen creation failed so set to safe settings.
getSettings()->setValue("fullscreen","0");
getSettings()->setValue("width",convertInt(resolutionList[lastRes].w));
getSettings()->setValue("height",convertInt(resolutionList[lastRes].h));
if(!createScreen()){
//Everything fails so quit.
setNextState(STATE_EXIT);
return;
}
}
//The screen is created, now load the (menu) theme.
if(!loadTheme("")){
//Loading the theme failed so quit.
setNextState(STATE_EXIT);
return;
}
}
if(langs->value!=lastLang){
//We set the language.
language=langValues.at(langs->value);
dictionaryManager->set_language(tinygettext::Language::from_name(langValues.at(langs->value)));
getLevelPackManager()->updateLanguage();
//And reload the font.
if(!loadFonts()){
//Loading failed so quit.
setNextState(STATE_EXIT);
return;
}
}
//Now return to the main menu.
setNextState(STATE_MENU);
- }else if(name=="cmdKeys"){
- inputMgr.showConfig();
- }else if(name=="cmdReset"){
- if(msgBox(_("Do you really want to reset level progress?"),MsgBoxYesNo,_("Warning"))==MsgBoxYes){
- //We delete the progress folder.
-#ifdef WIN32
- removeDirectory((getUserPath()+"progress").c_str());
- createDirectory((getUserPath()+"progress").c_str());
-#else
- removeDirectory((getUserPath(USER_DATA)+"/progress").c_str());
- createDirectory((getUserPath(USER_DATA)+"/progress").c_str());
-#endif
- //Resets statistics.
- statsMgr.reloadCompletedLevelsAndAchievements();
- }
- return;
}else if(name=="chkFullscreen"){
fullscreen=obj->value?true:false;
//Check if fullscreen changed.
if(fullscreen==getSettings()->getBoolValue("fullscreen")){
//We disable the restart message flag.
restartFlag=false;
}else{
//We set the restart message flag.
restartFlag=true;
}
}else if(name=="chkLeveltheme"){
leveltheme=obj->value?true:false;
}else if(name=="chkInternet"){
internet=obj->value?true:false;
}else if(name=="chkProxy"){
useProxy=obj->value?true:false;
}
}
if(name=="lstTheme"){
if(theme!=NULL && theme->value>=0 && theme->value<(int)theme->item.size()){
//Check if the theme is installed in the data path.
if(themeLocations[theme->item[theme->value]].find(getDataPath())!=string::npos){
themeName="%DATA%/themes/"+fileNameFromPath(themeLocations[theme->item[theme->value]]);
}else if(themeLocations[theme->item[theme->value]].find(getUserPath(USER_DATA))!=string::npos){
themeName="%USER%/themes/"+fileNameFromPath(themeLocations[theme->item[theme->value]]);
}else{
themeName=themeLocations[theme->item[theme->value]];
}
}
}else if(name=="txtProxy"){
internetProxy=obj->caption;
//Check if the internetProxy field is empty.
useProxy=!internetProxy.empty();
}else if(name=="sldMusic"){
getMusicManager()->setEnabled(musicSlider->value>0);
getMusicManager()->setVolume(musicSlider->value);
}else if(name=="sldSound"){
Mix_Volume(-1,soundSlider->value);
if(lastJumpSound==0){
Mix_PlayChannel(-1,jumpSound,0);
lastJumpSound=15;
}
}
+ if(name=="lstTabs"){
+ if(obj->value==0){
+ tabGeneral->visible=true;
+ tabControls->visible=false;
+ }else{
+ tabGeneral->visible=false;
+ tabControls->visible=true;
+ }
+ }
}
void Options::handleEvents(){
+ //Get the x and y location of the mouse.
+ int x,y;
+ SDL_GetMouseState(&x,&y);
+
+ //Check icon.
+ if(event.type==SDL_MOUSEMOTION || event.type==SDL_MOUSEBUTTONDOWN){
+ if(y>=SCREEN_HEIGHT-56&&y<SCREEN_HEIGHT-8&&x>=SCREEN_WIDTH-56)
+ clearIconHower=true;
+ else
+ clearIconHower=false;
+ }
+
+ if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT && clearIconHower){
+ if(msgBox(_("Do you really want to reset level progress?"),MsgBoxYesNo,_("Warning"))==MsgBoxYes){
+ //We delete the progress folder.
+#ifdef WIN32
+ removeDirectory((getUserPath()+"progress").c_str());
+ createDirectory((getUserPath()+"progress").c_str());
+#else
+ removeDirectory((getUserPath(USER_DATA)+"/progress").c_str());
+ createDirectory((getUserPath(USER_DATA)+"/progress").c_str());
+#endif
+ //Reset statistics.
+ statsMgr.reloadCompletedLevelsAndAchievements();
+ }
+ }
+
//Check if we need to quit, if so enter the exit state.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
//Check if the escape button is pressed, if so go back to the main menu.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
}
void Options::logic(){
//Increase the lastJumpSound variable if needed.
if(lastJumpSound!=0){
lastJumpSound--;
}
}
void Options::render(){
//Draw background.
objThemes.getBackground(true)->draw(screen);
objThemes.getBackground(true)->updateAnimation();
+
//Now render the title.
applySurface((SCREEN_WIDTH-title->w)/2,40-TITLE_FONT_RAISE,title,screen,NULL);
+ //Check if an icon is selected/highlighted and draw tooltip
+ if(clearIconHower){
+ SDL_Color fg={0,0,0};
+ /// TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
+ SDL_Surface *surface=TTF_RenderUTF8_Blended(fontText,_("Clear Progress"),fg);
+ drawGUIBox(-2,SCREEN_HEIGHT-surface->h-2,surface->w+4,surface->h+4,screen,0xFFFFFFFF);
+ applySurface(0,SCREEN_HEIGHT-surface->h,surface,screen,NULL);
+ SDL_FreeSurface(surface);
+ }
+
+ //Draw icon.
+ applySurface(SCREEN_WIDTH-48,SCREEN_HEIGHT-48,clearIcon,screen,NULL);
+
//NOTE: The rendering of the GUI is done in Main.
}
void Options::resize(){
//Recreate the gui to fit the new resolution.
createGUI();
}
/////////////////////////CREDITS_MENU//////////////////////////////////
Credits::Credits(){
//Render the title.
title=TTF_RenderUTF8_Blended(fontTitle,_("Credits"),themeTextColor);
//Vector that will hold every line of the credits.
vector<string> credits;
//Open the AUTHORS file and read every line.
{
ifstream fin((getDataPath()+"/../AUTHORS").c_str());
if(!fin.is_open()) {
cerr<<"ERROR: Unable to open the AUTHORS file."<<endl;
credits.push_back("ERROR: Unable to open the AUTHORS file.");
credits.push_back("");
}
//Loop the lines of the file.
string line;
while(getline(fin,line)){
credits.push_back(line);
}
}
//Enter a new line between the two files.
credits.push_back("");
//Open the Credits.text file and read every line.
{
ifstream fin((getDataPath()+"/Credits.txt").c_str());
if(!fin.is_open()) {
cerr<<"ERROR: Unable to open the Credits.txt file."<<endl;
credits.push_back("ERROR: Unable to open the Credits.txt file.");
credits.push_back("");
}
//Loop the lines of the file.
string line;
while(getline(fin,line)){
credits.push_back(line);
//NOTE: Some sections point to other credits files.
if(line=="music/") {
vector<string> musicCredits=getMusicManager()->createCredits();
credits.insert(credits.end(),musicCredits.begin(),musicCredits.end());
}
}
}
//Create the root element of the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,GUIObjectNone);
//Create back button.
backButton=new GUIObject(SCREEN_WIDTH*0.5,SCREEN_HEIGHT-60,-1,36,GUIObjectButton,_("Back"),0,true,true,GUIGravityCenter);
backButton->name="cmdBack";
backButton->eventCallback=this;
GUIObjectRoot->addChild(backButton);
//Create a text area for credits.
textArea=new GUITextArea(SCREEN_WIDTH*0.05,114,SCREEN_WIDTH*0.9,SCREEN_HEIGHT-200);
textArea->setFont(fontMono);
textArea->setStringArray(credits);
textArea->editable=false;
GUIObjectRoot->addChild(textArea);
}
Credits::~Credits(){
//Delete the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Free images
SDL_FreeSurface(title);
}
void Credits::GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Check what type of event it was.
if(eventType==GUIEventClick){
if(name=="cmdBack"){
//Goto the main menu.
setNextState(STATE_MENU);
}
}
}
void Credits::handleEvents(){
//Check if we need to quit, if so enter the exit state.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
//Check if the escape button is pressed, if so go back to the main menu.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
}
void Credits::logic(){
}
void Credits::render(){
//Draw background.
objThemes.getBackground(true)->draw(screen);
objThemes.getBackground(true)->updateAnimation();
//Now render the title.
applySurface((SCREEN_WIDTH-title->w)/2,40-TITLE_FONT_RAISE,title,screen,NULL);
//NOTE: The rendering of the GUI is done in Main.
}
void Credits::resize(){
//Resize and position widgets.
GUIObjectRoot->width=SCREEN_WIDTH;
GUIObjectRoot->height=SCREEN_HEIGHT;
backButton->left=SCREEN_WIDTH*0.5;
backButton->top=SCREEN_HEIGHT-60;
textArea->left=SCREEN_WIDTH*0.05;
textArea->width=SCREEN_WIDTH*0.9;
textArea->height=SCREEN_HEIGHT-200;
textArea->resize();
}
diff --git a/src/TitleMenu.h b/src/TitleMenu.h
index ff85dcf..84c6b51 100644
--- a/src/TitleMenu.h
+++ b/src/TitleMenu.h
@@ -1,148 +1,160 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TITLE_MENU_H
#define TITLE_MENU_H
#include <SDL/SDL.h>
#include "GameState.h"
//Included for the Options menu.
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUISlider.h"
#include "GUITextArea.h"
-
+#include "InputManager.h"
//The Main menu.
class Menu : public GameState{
private:
//The title of the main menu.
SDL_Surface* title;
//Array containg pointers to the five main menu entries.
//The last two are the '>' and '<' characters.
SDL_Surface* entries[7];
//The icon for the statistics menu.
SDL_Surface* statisticsIcon;
//The icon for the credits menu.
SDL_Surface* creditsIcon;
//Integer used for animations.
int animation;
public:
//Constructor.
Menu();
//Destructor.
~Menu();
//Inherited from GameState.
void handleEvents();
void logic();
void render();
void resize();
};
//The Options menu.
class Options : public GameState, private GUIEventCallback{
private:
//The title of the options menu.
SDL_Surface* title;
+
+ //Icon.
+ SDL_Surface* clearIcon;
+ bool clearIconHower;
//Slider used to set the music volume
GUISlider* musicSlider;
//Slider used to set the sound volume
GUISlider* soundSlider;
//Integer to keep track of the time passed since last playing the test sound.
int lastJumpSound;
//ListBox containing the themes the user can choose out.
GUISingleLineListBox* theme;
//Map containing the locations the themes are stored.
//The key is the name of the theme and the value the path.
std::map<std::string,std::string> themeLocations;
//Available languages
GUISingleLineListBox* langs;
std::vector<std::string> langValues;
//Resolution list
GUISingleLineListBox* resolutions;
+ //Containers for different tabs.
+ GUIObject* tabGeneral;
+ GUIObject* tabControls;
+
+ //Keys.
+ int tmpKeys[INPUTMGR_MAX];
+ int tmpAlternativeKeys[INPUTMGR_MAX];
+
//GUI events are handled here.
//name: The name of the element that invoked the event.
//obj: Pointer to the object that invoked the event.
//eventType: Integer containing the type of event.
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType);
public:
//Constructor.
Options();
//Destructor.
~Options();
//Method that will create the GUI for the options menu.
void createGUI();
//Inherited from GameState.
void handleEvents();
void logic();
void render();
void resize();
};
//A very simple structure for resolutions
struct _res{
int w,h;
};
//The Credits menu.
class Credits : public GameState, private GUIEventCallback{
private:
//The title of the credits menu.
SDL_Surface* title;
//Widgets.
GUITextArea* textArea;
GUIObject* backButton;
//GUI events are handled here.
//name: The name of the element that invoked the event.
//obj: Pointer to the object that invoked the event.
//eventType: Integer containing the type of event.
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType);
public:
//Constructor.
Credits();
//Destructor.
~Credits();
//Inherited from GameState.
void handleEvents();
void logic();
void render();
void resize();
};
#endif

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 16, 9:48 AM (23 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
64145
Default Alt Text
(71 KB)

Event Timeline