Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F130033
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
40 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/GUIObject.cpp b/src/GUIObject.cpp
index b2d144b..1ef6de5 100644
--- a/src/GUIObject.cpp
+++ b/src/GUIObject.cpp
@@ -1,527 +1,526 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. 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);
//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);
//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());
}else if(event.key.keysym.sym==SDLK_LEFT){
value=clamp(value-1,0,caption.length());
}
//The event has been processed.
b=true;
}
//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;
}
//Check for a mouse button press.
if(k&SDL_BUTTON(1)){
//We have focus.
state=2;
//TODO Move carrot to place clicked
value=caption.length();
}
}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;
}
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){
//Color the text will be: black.
SDL_Color black={0,0,0,0};
cache=TTF_RenderUTF8_Blended(fontText,lp,black);
- if(width<=0){
+ if(width<=0)
width=cache->w;
- if(gravity==GUIGravityCenter){
- gravityX=int(width/2);
- }else if(gravity==GUIGravityRight){
- gravityX=width;
- }else{
- gravityX=0;
- }
- }
+
+ if(gravity==GUIGravityCenter)
+ gravityX=(width-cache->w)/2;
+ else if(gravity==GUIGravityRight)
+ gravityX=width+cache->w;
+ else
+ gravityX=0;
}
if(draw){
//Center the text vertically and draw it to the screen.
r.y=y+(height - cache->h)/2;
- r.x-=gravityX;
+ 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 black={0,0,0,0};
cache=TTF_RenderUTF8_Blended(fontText,lp,black);
}
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){
//Draw black text.
SDL_Color black={0,0,0,0};
//Draw in gray when disabled.
if(!enabled)
black.r=black.g=black.b=96;
if(!smallFont)
cache=TTF_RenderUTF8_Blended(fontGUI,lp,black);
else
cache=TTF_RenderUTF8_Blended(fontGUISmall,lp,black);
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){
applySurface(x-gravityX+(width-cache->w)/2-25,y+(height-cache->h)/2+((cache->h-16)/2),bmGUI,screen,&r2);
r2.x-=16;
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w+5,y+(height-cache->h)/2+((cache->h-16)/2),bmGUI,screen,&r2);
}else if(state==2){
applySurface(x-gravityX+(width-cache->w)/2-20,y+(height-cache->h)/2+((cache->h-16)/2),bmGUI,screen,&r2);
r2.x-=16;
applySurface(x-gravityX+(width-cache->w)/2+4+cache->w,y+(height-cache->h)/2+((cache->h-16)/2),bmGUI,screen,&r2);
}
}
//Draw the text and free the surface.
SDL_BlitSurface(cache,NULL,screen,&r);
}
}
}
break;
case GUIObjectTextBox:
{
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){
//The colors black and white used to render the title with white background.
SDL_Color black={0,0,0,0};
cache=TTF_RenderUTF8_Blended(fontGUI,lp,black);
}
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 c14250f..17e82e5 100644
--- a/src/InputManager.cpp
+++ b/src/InputManager.cpp
@@ -1,443 +1,443 @@
/****************************************************************************
** Copyright (C) 2012 me and my shadow developers
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. 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 <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_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)"),
__("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)")
};
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->item[index]=s;
}
public:
//Constructor.
InputDialogHandler(GUIListBox* listBox,InputManager* parent):listBox(listBox),parent(parent),isAlternativeKey(false){
//load the avaliable 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->item.push_back(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"){
onKeyDown(0);
}else if(name=="lstType"){
isAlternativeKey=(obj->value==1);
for(int i=0;i<INPUTMGR_MAX;i++){
updateConfigItem(i);
}
}
/*else if(name=="cmdEscape"){
//set a key to Escape
//simply call onKeyDown().
onKeyDown(SDLK_ESCAPE);
}*/
}
}
};
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(){
//Save the old GUI.
GUIObject* tmp=GUIObjectRoot;
//Create the new GUI.
GUIObjectRoot=new GUIObject((SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-420)/2,600,400,GUIObjectFrame,_("Config Keys"));
GUIObject* obj;
- obj=new GUIObject(GUIObjectRoot->width*0.5,44,-1,36,GUIObjectLabel,_("Select an item and press a key to config it."),0,true,true,GUIGravityCenter);
+ obj=new GUIObject(0,44,GUIObjectRoot->width,36,GUIObjectLabel,_("Select an item and press a key to config it."),0,true,true,GUIGravityCenter);
GUIObjectRoot->childControls.push_back(obj);
//The list box.
GUIListBox *listBox=new GUIListBox(20,126,560,220);
//Event handler.
InputDialogHandler handler(listBox,this);
GUIObjectRoot->childControls.push_back(listBox);
//another box to select key type
GUISingleLineListBox *listBox0=new GUISingleLineListBox(120,80,360,36);
listBox0->name="lstType";
listBox0->item.push_back(_("Primary key"));
listBox0->item.push_back(_("Alternative key"));
listBox0->value=0;
listBox0->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(listBox0);
//two buttons
obj=new GUIObject(32,360,-1,36,GUIObjectButton,_("Unset the key"),0,true,true,GUIGravityLeft);
obj->name="cmdUnset";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
/*
obj=new GUIObject(20,360,360,36,GUIObjectButton,"Set to ESCAPE key");
obj->name="cmdEscape";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
*/
obj=new GUIObject(GUIObjectRoot->width-32,360,-1,36,GUIObjectButton,_("OK"),0,true,true,GUIGravityRight);
obj->name="cmdOK";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
//Now we keep rendering and updating the GUI.
SDL_FillRect(tempSurface,NULL,0);
SDL_SetAlpha(tempSurface,SDL_SRCALPHA,155);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
while(GUIObjectRoot){
while(SDL_PollEvent(&event)){
//check if some key is down.
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);
}
}
//now process GUI events.
GUIObjectHandleEvents(true);
}
if(GUIObjectRoot)
GUIObjectRoot->render();
flipScreen();
SDL_Delay(30);
}
//Restore the old GUI.
GUIObjectRoot=tmp;
}
//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/LevelSelect.cpp b/src/LevelSelect.cpp
index e17a9dd..5bb7a34 100644
--- a/src/LevelSelect.cpp
+++ b/src/LevelSelect.cpp
@@ -1,402 +1,401 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "Globals.h"
#include "Objects.h"
#include "LevelSelect.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUIScrollBar.h"
#include "InputManager.h"
#include "Game.h"
#include <SDL/SDL_ttf.h>
#include <SDL/SDL.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include "libs/tinyformat/tinyformat.h"
using namespace std;
////////////////////NUMBER////////////////////////
Number::Number(){
image=NULL;
number=0;
medal=0;
selected=false;
locked=false;
//Set the default dimensions.
box.x=0;
box.y=0;
box.h=50;
box.w=50;
//Load the medals image.
background=loadImage(getDataPath()+"gfx/level.png");
backgroundLocked=loadImage(getDataPath()+"gfx/levellocked.png");
medals=loadImage(getDataPath()+"gfx/medals.png");
}
Number::~Number(){
//We only need to free the SDLSurface.
if(image) SDL_FreeSurface(image);
}
void Number::init(int number,SDL_Rect box){
//First set the number and update our status.
this->number=number;
//Write our text, number+1 since the counting doens't start with 0, but with 1.
std::stringstream text;
number++;
text<<number;
//Create the text image.
SDL_Color black={0,0,0};
if(image) SDL_FreeSurface(image);
//Create the text image.
//Also check which font to use, if the number is higher than 100 use the small font.
image=TTF_RenderUTF8_Blended(fontGUI,text.str().c_str(),black);
//Set the new location of the number.
this->box.x=box.x;
this->box.y=box.y;
}
void Number::init(std::string text,SDL_Rect box){
//First set the number and update our status.
this->number=-1;
//Create the text image.
SDL_Color black={0,0,0};
if(image) SDL_FreeSurface(image);
image=TTF_RenderUTF8_Blended(fontGUI,text.c_str(),black);
//Set the new location of the number.
this->box.x=box.x;
this->box.y=box.y;
}
void Number::show(int dy){
//First draw the background, also apply the yOffset(dy).
if(!locked)
applySurface(box.x,box.y-dy,background,screen,NULL);
else
applySurface(box.x,box.y-dy,backgroundLocked,screen,NULL);
//Now draw the text image over the background.
//We draw it centered inside the box.
applySurface((box.x+25-(image->w/2)),box.y-dy,image,screen,NULL);
//Draw the selection mark.
if(selected){
drawGUIBox(box.x,box.y-dy,50,50,screen,0xFFFFFF23);
}
//Draw the medal.
if(medal>0){
SDL_Rect r={(medal-1)*30,0,30,30};
applySurface(box.x+30,(box.y+30)-dy,medals,screen,&r);
}
}
void Number::setLocked(bool locked){
this->locked=locked;
}
void Number::setMedal(int medal){
this->medal=medal;
}
/////////////////////LEVEL SELECT/////////////////////
LevelSelect::LevelSelect(string titleText,LevelPackManager::LevelPackLists packType){
//clear the selected level
selectedNumber=NULL;
//Calculate the LEVELS_PER_ROW and LEVEL_ROWS if they aren't calculated already.
calcRows();
//Render the title.
SDL_Color black={0,0,0};
title=TTF_RenderUTF8_Blended(fontTitle,titleText.c_str(),black);
//create GUI (test only)
GUIObject* obj;
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//the level select scroll bar
levelScrollBar=new GUIScrollBar(SCREEN_WIDTH*0.9,184,16,SCREEN_HEIGHT-344,ScrollBarVertical,0,0,0,1,4,true,false);
GUIObjectRoot->childControls.push_back(levelScrollBar);
//level pack description
- levelpackDescription=new GUIObject(SCREEN_WIDTH*0.5,140,-1,32,GUIObjectLabel,"",0,true,true,GUIGravityCenter);
+ levelpackDescription=new GUIObject(0,140,SCREEN_WIDTH,32,GUIObjectLabel,"",0,true,true,GUIGravityCenter);
GUIObjectRoot->childControls.push_back(levelpackDescription);
levelpacks=new GUISingleLineListBox((SCREEN_WIDTH-500)/2,104,500,32);
levelpacks->name="cmdLvlPack";
levelpacks->eventCallback=this;
vector<string> v=getLevelPackManager()->enumLevelPacks(packType);
levelpacks->item=v;
levelpacks->value=0;
//Check if we can find the lastlevelpack.
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
if(*i==getSettings()->getValue("lastlevelpack")){
levelpacks->value=i-v.begin();
}
}
//Get the name of the selected levelpack.
string levelpackName=levelpacks->item[levelpacks->value];
string s1=getUserPath(USER_DATA)+"progress/"+levelpackName+".progress";
//Load the progress.
levels=getLevelPackManager()->getLevelPack(v[levelpacks->value]);
levels->loadProgress(s1);
//And add the levelpack single line listbox to the GUIObjectRoot.
GUIObjectRoot->childControls.push_back(levelpacks);
obj=new GUIObject(20,20,-1,32,GUIObjectButton,_("Back"));
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
section=0;
}
LevelSelect::~LevelSelect(){
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
levelScrollBar=NULL;
levelpackDescription=NULL;
selectedNumber=NULL;
//Free the rendered title surface.
SDL_FreeSurface(title);
}
void LevelSelect::calcRows(){
//Calculate the number of rows and the number of levels per row.
LEVELS_PER_ROW=(SCREEN_WIDTH*0.8)/64;
int LEVEL_ROWS=(SCREEN_HEIGHT-344)/64;
LEVELS_DISPLAYED_IN_SCREEN=LEVELS_PER_ROW*LEVEL_ROWS;
}
void LevelSelect::selectNumberKeyboard(int x,int y){
if(section==2){
//Move selection
int realNumber=selectedNumber->getNumber()+x+(y*LEVELS_PER_ROW);
//If selection is outside of the map grid, change section
if(realNumber<0 || realNumber>numbers.size()-1){
section=1;
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=false;
}
}else{
//If not, move selection
if(!numbers[realNumber].getLocked()){
selectNumber(realNumber,false);
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=(i==realNumber);
}
}
}
}else if(section==1){
//Loop through levelpacks and update GUI
levelpacks->value+=x;
if(levelpacks->value<0){
levelpacks->value=levelpacks->item.size()-1;
}else if(levelpacks->value>levelpacks->item.size()-1){
levelpacks->value=0;
}
GUIEventCallback_OnEvent("cmdLvlPack",static_cast<GUIObject*>(levelpacks),0);
//If up is pressed, change section
if(y==1){
section=2;
selectNumber(0,false);
numbers[0].selected=true;
}
}else{
section=clamp(section+y,0,2);
}
}
void LevelSelect::handleEvents(){
//Check for an SDL_QUIT event.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
//Check for a mouse click.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT){
checkMouse();
}
//Check focus movement
if(inputMgr.isKeyDownEvent(INPUTMGR_RIGHT)){
selectNumberKeyboard(1,0);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_LEFT)){
selectNumberKeyboard(-1,0);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_UP)){
selectNumberKeyboard(0,-1);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_DOWN)){
selectNumberKeyboard(0,1);
}
//Check if enter is pressed
if(section==2 && inputMgr.isKeyUpEvent(INPUTMGR_SELECT)){
selectNumber(selectedNumber->getNumber(),true);
}
//Check if escape is pressed.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
//Check for scrolling down and up.
if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELDOWN && levelScrollBar){
if(levelScrollBar->value<levelScrollBar->maxValue) levelScrollBar->value++;
return;
}else if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELUP && levelScrollBar){
if(levelScrollBar->value>0) levelScrollBar->value--;
return;
}
}
void LevelSelect::checkMouse(){
int x,y,dy=0,m=numbers.size();
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
//Check if there's a scrollbar, if so get the value.
if(levelScrollBar)
dy=levelScrollBar->value;
//Upper bound of levels we'd like to display.
if(m>dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN)
m=dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
for(int n=dy*LEVELS_PER_ROW; n<m; n++){
if(!numbers[n].getLocked()){
if(checkCollision(mouse,numbers[n].box)==true){
if(numbers[n].selected){
selectNumber(n,true);
}else{
//Select current level
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=(i==n);
}
selectNumber(n,false);
}
section=2;
break;
}
}
}
}
void LevelSelect::logic(){}
void LevelSelect::render(){
int x,y,dy=0,m=numbers.size();
int idx=-1;
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
if(levelScrollBar)
dy=levelScrollBar->value;
//Upper bound of levels we'd like to display.
if(m>dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN)
m=dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
//Draw the menu background.
applySurface(0,0,menuBackground,screen,NULL);
//Draw the title.
applySurface((SCREEN_WIDTH-title->w)/2,40-TITLE_FONT_RAISE,title,screen,NULL);
//Loop through the level blocks and draw them.
for(int n=dy*LEVELS_PER_ROW;n<m;n++){
numbers[n].show(dy*64);
if(numbers[n].getLocked()==false && checkCollision(mouse,numbers[n].box)==true)
idx=n;
}
//Show the tool tip text.
if(idx>=0){
renderTooltip(idx,dy);
}
}
void LevelSelect::resize(){
calcRows();
refresh();
//NOTE: We don't need to recreate the listbox and the back button, only resize the list.
levelpacks->left=(SCREEN_WIDTH-500)/2;
- levelpackDescription->left=SCREEN_WIDTH*0.5;
}
void LevelSelect::GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
string s;
if(name=="cmdLvlPack"){
getSettings()->setValue("lastlevelpack",static_cast<GUISingleLineListBox*>(obj)->item[obj->value]);
}else if(name=="cmdBack"){
setNextState(STATE_MENU);
return;
}else{
return;
}
//new: reset the level list scroll bar
if(levelScrollBar)
levelScrollBar->value=0;
string s1=getUserPath(USER_DATA)+"progress/"+static_cast<GUISingleLineListBox*>(obj)->item[obj->value]+".progress";
levels=getLevelPackManager()->getLevelPack(static_cast<GUISingleLineListBox*>(obj)->item[obj->value]);
//Load the progress file.
levels->loadProgress(s1);
//And refresh the numbers.
refresh();
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Jun 15, 11:22 PM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
69934
Default Alt Text
(40 KB)
Attached To
Mode
R79 meandmyshadow
Attached
Detach File
Event Timeline