#include #include #include #include #include "gamemem.h" #include "textures.h" #include "gametime.h" #include "interface.h" #include "interfaceutil.h" #include "vectors.h" #include "text.h" #include "controls.h" #include "screen.h" #include "carphysics.h" #include "gamesystem.h" #include "gamesound.h" #include "random.h" #include "interfacemultiplayer.h" #include "log.h" #include "initexit.h" int gJoinFlag=false; int gInterfaceType=false; char gJoinHost[256]; char gLastMenuChar; float gStartIdleTime=0; /* #define kNumEasterEggStrings 3 char gEasterEggStrings[kNumEasterEggStrings][256]={ "Easter Egg not yet implemented...", "Bla Bla", "Insert Funny Stuff here" }; /*/ #define kNumEasterEggStrings 10 char gEasterEggStrings[kNumEasterEggStrings][256]={ "You better respect me, 'cos I'm the man with the car with the star", "It's a long way to the top (if you wanna rock'n'roll!)", "There's no replacement for displacement", "echo \"carsOnSpeed 1\" >> ~/Library/Preferences/Redline\ Preferences", "Moof!", "All your horsepower are belong to us", "Frog blast the vent core!", "\255#w\255Everyone likes \255#r\255c\255#y\255o\255#g\255l\255#c\255o\255#b\255r\255#w\255 tags: \\255#r\\255", "In Soviet Russia, car drives you!", "out of errors." }; #define kEasterEggScrollSpeed 0.8 #define kMenuFPS 75.0 #define kMenuFrameTime (1/kMenuFPS) #define kMenuSuspendedFPS 0.5 #define kMenuSuspendedFrameTime (1/kMenuSuspendedFPS) void InterfaceDrawBackgroundFade(float opacity,int showtop) { gTexturesQualityModifier=-255; if(opacity==0) return; glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_TEXTURE_BIT+GL_CURRENT_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(1,1,1,opacity); TexturesSelectTex(FileGetReference(kInterfaceBackgroundTexture)); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); if(showtop) { glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch); glEnd(); TexturesSelectTex(FileGetReference("menustripe.tif")); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch, 0.7*kScreenYPos); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch, 1.0*kScreenYPos); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,0.7*kScreenYPos); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,1.0*kScreenYPos); glEnd(); } else { if(ScreenSupportsBlendColor()) { glBlendFunc(GL_CONSTANT_ALPHA,GL_ONE_MINUS_CONSTANT_ALPHA); glBlendColor(1,1,1,opacity); } glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(1,0.15); glVertex2f(kBackgroundXStretch,kBackgroundYStretch-0.3*kBackgroundXStretch); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(0,0.15); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-0.3*kBackgroundXStretch); glEnd(); } glDisable(GL_TEXTURE_2D); glColor4f(0,0,0,opacity); glBegin(GL_TRIANGLE_STRIP); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch); glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch); glEnd(); glBegin(GL_TRIANGLE_STRIP); glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch); glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); glEnd(); glPopAttrib(); gTexturesQualityModifier=0; } void InterfaceDrawBackground(tFileRef background,tFileRef image,float imageXScale,float imageYScale,float imageXPos,float imageYPos,float alpha) { glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); gTexturesQualityModifier=-255; glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glClear(GL_COLOR_BUFFER_BIT); if(background!=kFileErr) TexturesSelectTex(background); else TexturesSelectTex(FileGetReference(kInterfaceBackgroundTexture)); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); /* glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,-kBackgroundYStretch); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,-kBackgroundYStretch); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch); glEnd(); */ glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch); glEnd(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); TexturesSelectTex(FileGetReference("menustripe.tif")); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch, 0.7*kScreenYPos); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch, 1.0*kScreenYPos); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,0.7*kScreenYPos); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,1.0*kScreenYPos); glEnd(); if(image!=kFileErr) { glColor4f(1,1,1,alpha); TexturesSelectTex(image); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(imageXPos+imageXScale,imageYPos-imageYScale); glTexCoord2d(1,0); glVertex2f(imageXPos+imageXScale,imageYPos+imageYScale); glTexCoord2d(0,1); glVertex2f(imageXPos-imageXScale,imageYPos-imageYScale); glTexCoord2d(0,0); glVertex2f(imageXPos-imageXScale,imageYPos+imageYScale); glEnd(); } glPopAttrib(); gTexturesQualityModifier=0; } void InterfaceFadeInImageFromBlack(float xSize,float ySize,tFileRef image,float maxTime) { gTexturesQualityModifier=-255; TexturesSelectTex(image); float startTime=TimeGetSeconds(); float time=0; int exit=false; glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); while(!exit) { time=TimeGetSeconds()-startTime; float alpha=(time/maxTime); glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_COLOR_BUFFER_BIT+GL_LIGHTING_BIT+GL_TEXTURE_BIT+GL_CURRENT_BIT); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(1,1,1,alpha); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch*xSize,-kBackgroundYStretch*ySize); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch*xSize,kBackgroundYStretch*ySize); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch*xSize,-kBackgroundYStretch*ySize); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch*xSize,kBackgroundYStretch*ySize); glEnd(); glPopAttrib(); ScreenBlit(); if(time>=maxTime) exit=true; } gTexturesQualityModifier=0; } void InterfaceFadeInImageFromImage(float xSize,float ySize,tFileRef image,float xSize2,float ySize2,tFileRef image2,float maxTime) { gTexturesQualityModifier=-255; float startTime=TimeGetSeconds(); float time=0; int exit=false; glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); while(!exit) { time=TimeGetSeconds()-startTime; float alpha=(time/maxTime); glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_COLOR_BUFFER_BIT+GL_LIGHTING_BIT+GL_TEXTURE_BIT+GL_CURRENT_BIT); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); TexturesSelectTex(image); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch*xSize,-kBackgroundYStretch*ySize); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch*xSize,kBackgroundYStretch*ySize); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch*xSize,-kBackgroundYStretch*ySize); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch*xSize,kBackgroundYStretch*ySize); glEnd(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(1,1,1,alpha); TexturesSelectTex(image2); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch*xSize2,-kBackgroundYStretch*ySize2); glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch*xSize2,kBackgroundYStretch*ySize2); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch*xSize2,-kBackgroundYStretch*ySize2); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch*xSize2,kBackgroundYStretch*ySize2); glEnd(); glPopAttrib(); ScreenBlit(); if(time>=maxTime) exit=true; } gTexturesQualityModifier=0; } void InterfaceFadeInInterfaceFromImage(tFileRef image,float maxTime) { float startTime=TimeGetSeconds(); float time=0; int exit=false; glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); while(!exit) { time=TimeGetSeconds()-startTime; float alpha=1-(time/maxTime); InterfaceDrawBackground(-1,image,kBackgroundXStretch,kBackgroundYStretch,0,0,alpha); ScreenBlit(); if(time>=maxTime) exit=true; } } void InterfaceDrawStrings(char *stringBuffer,char *secondaryStringBuffer,tFileRef background) { InterfaceDrawBackground(background,-1,0,0,0,0,1); TextPrintfToBufferFormated(Vector(kTitlePosX,kTitlePosY),0.08,kTextAlignLeft,stringBuffer); TextPrintfToBufferFormated(Vector(-0.9,0.5),0.05,kTextAlignLeft,secondaryStringBuffer); // TextPrintfToBufferFormated(Vector(-1,0.97),0.03,kTextAlignLeft,gInterfaceMenuPath); TextPrintBuffer(1,false); TextClearBuffer(); ScreenBlit(); } void InterfaceDrawStatusBar(char *stringBuffer,char *secondaryStringBuffer,float status) { InterfaceDrawBackground(-1,-1,0,0,0,0,1); TextPrintfToBufferFormated(Vector(kTitlePosX,kTitlePosY),0.08,kTextAlignLeft,stringBuffer); TextPrintfToBufferFormated(Vector(-0.9,0.5),0.05,kTextAlignLeft,secondaryStringBuffer); // TextPrintfToBufferFormated(Vector(-1,0.97),0.03,kTextAlignLeft,gInterfaceMenuPath); TextPrintBuffer(1,false); TextClearBuffer(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); gTexturesQualityModifier=-255; TexturesSelectTex(FileGetReference("progress.pct")); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(status,1); glVertex2f(-kBackgroundXStretch*0.8+kBackgroundXStretch*1.6*status,-kBackgroundYStretch*0.1); glTexCoord2d(status,0); glVertex2f(-kBackgroundXStretch*0.8+kBackgroundXStretch*1.6*status,kBackgroundYStretch*0.1); glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch*0.8,-kBackgroundYStretch*0.1); glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch*0.8,kBackgroundYStretch*0.1); glEnd(); glPopAttrib(); ScreenBlit(); gTexturesQualityModifier=0; } void MenuSubTitleCallback(char *text,int selection,void *menu) { TextPrintfToBufferFormated(Vector(-0.85,0.6),0.05,kTextAlignLeft|kTextAutoWrap,text); } int InterfaceGetUserConfirmation(char *title,char *text) { tInterfaceMenuDescribtion menu; InterfaceInitMenu(&menu,2,title); menu.RenderCallback=(void(*)(void*,int,void*))MenuSubTitleCallback; menu.userData=text; menu.itemsYPos=0.2; char itemStrings[][32]={"OK","Cancel"}; for(int i=0;i0) stringBuffer[--len]='\0'; if(ch>=(fullCharSet?' ':'-')&&ch<='z'&&len=1000000) sprintf(str,"$%d,%03d,%03d",cash/1000000,(cash/1000)%1000,cash%1000); else if(cash>=1000) sprintf(str,"$%d,%03d",cash/1000,cash%1000); else sprintf(str,"$%d",cash); } void MakeNumString(int i,char *str) { if((i%10)==1&&i!=11) sprintf(str,"1st"); else if((i%10)==2&&i!=12) sprintf(str,"2nd"); else if((i%10)==3&&i!=13) sprintf(str,"3rd"); else sprintf(str,"%dth",i); } void InterfaceInitMenu(tInterfaceMenuDescribtion *menu,int numItems,char *title) { menu->items=(tInterfaceMenuItemDescribtion*)MemoryAllocateBlock(sizeof(tInterfaceMenuItemDescribtion)*numItems); strcpy(menu->title,title); menu->initialSelection=0; menu->numItems=numItems; menu->image=-1; menu->background=FileGetReference(kInterfaceBackgroundTexture); menu->scrollEnable=false; menu->joinDisable=false; menu->enterAlwaysOK=false; menu->easterEggEnable=false; menu->menuTypeable=false; menu->easterEggScrollPos=-10; menu->easterEggString=0; menu->imageXScale=kBackgroundXStretch; menu->imageYScale=kBackgroundYStretch; menu->imageAlpha=1.0; menu->imageXPos=0; menu->imageYPos=0; menu->itemsXPos=-0.9; menu->itemsYPos=0.55; menu->minScroll=-0.75; menu->type[0]='\0'; menu->returnOnSpace=false; menu->cursorShowPos=10000; menu->cursorPos=0; menu->descPos=Vector(0.3,0.55); menu->mousePos=GetMousePos(); menu->RenderCallback=NULL; menu->TimerCallback=NULL; menu->userData=NULL; for(int i=0;iitems[i].sel=0; menu->items[i].label[0]='\0'; menu->items[i].describtion[0]='\0'; menu->items[i].type[0]='\0'; menu->items[i].size=0.05; menu->items[i].lineSpacing=0.15; menu->items[i].maxTypeXPos=0.95; menu->items[i].maxTypeLength=255; menu->items[i].sliderPos=0; menu->items[i].sliderTransparency=0; menu->items[i].r=1; menu->items[i].g=1; menu->items[i].b=1; menu->items[i].flags=0; } } void InterfaceDisposeMenu(tInterfaceMenuDescribtion *menu) { MemoryFreeBlock((tInterfaceMenuItemDescribtion*)menu->items); } void InterfaceMenuRender(tInterfaceMenuDescribtion *menu,int selection,float backgroundAlpha) { static float lt=0; float t=TimeGetSeconds(); float dt=t-lt; lt=t; gTexturesQualityModifier=-255; if(menu->background!=kFileErr) InterfaceDrawBackground(menu->background,menu->image,menu->imageXScale,menu->imageYScale,menu->imageXPos,menu->imageYPos,menu->imageAlpha*backgroundAlpha); gTexturesQualityModifier=0; if(menu->RenderCallback) menu->RenderCallback(menu->userData,selection,menu); gTexturesQualityModifier=-255; float line=menu->itemsYPos; float selOffset=line; if(selection!=-1&&menu->scrollEnable) { for(int i=0;iitems[i].flags&kInterfaceMenuItemFixedPos)) selOffset-=menu->items[i].lineSpacing; float lastOffset=selOffset; for(int i=selection;inumItems;i++) if(!(menu->items[i].flags&kInterfaceMenuItemFixedPos)) lastOffset-=menu->items[i].lineSpacing; if(lastOffsetminScroll) line+=((menu->itemsYPos-selOffset)/(menu->itemsYPos-lastOffset))*((menu->itemsYPos-lastOffset)-(menu->itemsYPos-menu->minScroll)); } for(int i=0;inumItems;i++) { if((line<=menu->itemsYPos+menu->items[i].lineSpacing*0.5&&line>=menu->minScroll)||(!menu->scrollEnable)||menu->items[i].flags&kInterfaceMenuItemFixedPos) { char hiddenType[256]; int ch; for(ch=0;chitems[i].type);ch++) hiddenType[ch]='*'; hiddenType[ch]='\0'; char str[256]; int j=0; int img=false; if(menu->items[i].flags&kInterfaceMenuItemTypeable) do { char *type=(menu->items[i].flags&kInterfaceMenuItemTypeHidden?hiddenType:menu->items[i].type)+j; sprintf(str,"%s\255#a\255%s",menu->items[i].label,type); if(j) if(type[-1]=='\255') img=!img; j++; } while((TextWidth(str,menu->items[i].size*(1+0.1*menu->items[i].sel))+menu->itemsXPos*kTextXPos>kTextXPos*menu->items[i].maxTypeXPos||img)&&j!=strlen(menu->items[i].type)); else strcpy(str,menu->items[i].label); float fullLength=TextWidth(str,menu->items[i].size*(1+0.1*menu->items[i].sel)); float visRatio=fullLength/(kTextXPos*(menu->items[i].maxTypeXPos-menu->itemsXPos)); float textshift=0; if(visRatio>1) { float scroll=menu->items[i].scroll/1.5f; if(selection==i) menu->items[i].scroll+=dt; else if(menu->items[i].scroll>2) menu->items[i].scroll=0; else if(menu->items[i].scroll>1) menu->items[i].scroll=2-menu->items[i].scroll; else menu->items[i].scroll-=dt; float scrollsize; if(scroll<1) scrollsize=fullLength*(1-(1-(1/(visRatio+0.1)))*scroll); else if(scroll<2) scrollsize=fullLength*(1-(1-(1/(visRatio+0.1)))*(2-scroll)); else scrollsize=fullLength; char tmp[256]; strcpy(tmp,str); j=0; img=false; char color=-1; do { strcpy(str,tmp+j); if(j) if(tmp[j-1]=='\255') { img=!img; if(img&&tmp[j]=='#') color=tmp[j+1]; } j++; } while((TextWidth(str,menu->items[i].size*(1+0.1*menu->items[i].sel))>scrollsize||img)&&j!=strlen(tmp)); textshift=scrollsize-TextWidth(str,menu->items[i].size*(1+0.1*menu->items[i].sel)); if(color!=-1) { strcpy(tmp,str); sprintf(str,"\255#%c\255%s",color,tmp); } /* int scrollpos=0; if(scroll<1) scrollpos=(1-(1/visRatio))*strlen(str)*scroll; else if(scroll<2) scrollpos=(1-(1/visRatio))*strlen(str)*(2-scroll); memmove(str,str+scrollpos,strlen(str+scrollpos)+1);*/ } if(menu->items[i].scroll<0) menu->items[i].scroll=0; img=false; int l=strlen(str); while((TextWidth(str,menu->items[i].size*(1+0.1*menu->items[i].sel))+menu->itemsXPos*kTextXPos>kTextXPos*menu->items[i].maxTypeXPos||img)&&*str) { if(str[l-1]=='\255') img=!img; str[l-1]='\0'; l--; } if(menu->items[i].flags&kInterfaceMenuItemTypeable&&selection==i&&(int)(TimeGetSeconds()*4)%2) sprintf(str,"%s%s",str,"_"); float a=(menu->items[i].flags&kInterfaceMenuItemDisabled?0.5:1)*(0.8+(0.2*menu->items[i].sel*0.5*(sin(TimeGetSeconds()*8)+1) )); if(menu->items[i].flags&kInterfaceMenuItemFixedPos) TextPrintfToBufferFormatedColored(Vector(menu->items[i].fixedX,menu->items[i].fixedY+menu->items[i].size*0.1*menu->items[i].sel) ,menu->items[i].size*(1+0.1*menu->items[i].sel) ,kTextAlignLeft ,menu->items[i].r ,menu->items[i].g ,menu->items[i].b ,a ,str ); else TextPrintfToBufferFormatedColored(Vector(menu->itemsXPos+textshift,line+menu->items[i].size*0.1*menu->items[i].sel) ,menu->items[i].size*(1+0.1*menu->items[i].sel) ,kTextAlignLeft ,menu->items[i].r ,menu->items[i].g ,menu->items[i].b ,a ,str ); if(selection==i) if(menu->items[i].flags&kInterfaceMenuItemFixedPos) menu->cursorPos=(menu->items[i].fixedY-menu->items[i].size*1.3)*kScreenYPos; else menu->cursorPos=(line-menu->items[i].size*1.3)*kScreenYPos; if(menu->items[i].flags&kInterfaceMenuItemSlider) { glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); float y=(line-0.05)*kScreenYPos; glColor4f(1,1,1,(1-menu->items[i].sliderTransparency)*backgroundAlpha); TexturesSelectTex(FileGetReference(kInterfaceMenuSlideBarTexture)); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuSlideBarStart+kInterfaceMenuSlideBarWidth, y-kInterfaceMenuSlideBarHeight); glTexCoord2d(1,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuSlideBarStart+kInterfaceMenuSlideBarWidth, y+kInterfaceMenuSlideBarHeight); glTexCoord2d(0,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuSlideBarStart, y-kInterfaceMenuSlideBarHeight); glTexCoord2d(0,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuSlideBarStart, y+kInterfaceMenuSlideBarHeight); glEnd(); TexturesSelectTex(FileGetReference(kInterfaceMenuSliderTexture)); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+menu->items[i].sliderPos*kInterfaceMenuSlideBarWidth+kInterfaceMenuSlideBarStart+kInterfaceMenuSliderSize, y-kInterfaceMenuSliderSize); glTexCoord2d(1,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+menu->items[i].sliderPos*kInterfaceMenuSlideBarWidth+kInterfaceMenuSlideBarStart+kInterfaceMenuSliderSize, y+kInterfaceMenuSliderSize); glTexCoord2d(0,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+menu->items[i].sliderPos*kInterfaceMenuSlideBarWidth+kInterfaceMenuSlideBarStart-kInterfaceMenuSliderSize, y-kInterfaceMenuSliderSize); glTexCoord2d(0,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+menu->items[i].sliderPos*kInterfaceMenuSlideBarWidth+kInterfaceMenuSlideBarStart-kInterfaceMenuSliderSize, y+kInterfaceMenuSliderSize); glEnd(); glPopAttrib(); } } if(!(menu->items[i].flags&kInterfaceMenuItemFixedPos)) line-=menu->items[i].lineSpacing; } TextPrintfToBufferFormated(Vector(kTitlePosX,kTitlePosY),0.08,kTextAlignLeft,menu->title); float a=2-(TimeGetSeconds()-giTunesLastStatusUpdate)*0.4; if(a>0) { char str[1024]; if(giTunesPlaying==kITunesPlaying) sprintf(str,"%s - %s",giTunesArtist,giTunesSong); else if(giTunesPlaying==kITunesPaused) strcpy(str,"Paused"); else strcpy(str,"Stopped"); float screenRatio=(float)gConfig->screenXSize/(float)gConfig->screenYSize; float maxWidth=(0.1+screenRatio/(4.0/3.0))*kTextXPos; float scale=1; while(TextWidth(str,0.04*scale)>maxWidth) scale*=0.9; //printf("%f,%f/%f\n",size,TextWidth(str,size),maxWidth); TextPrintfToBufferFormatedColored(Vector(-0.1,0.95+0.05*scale),0.04*scale,kTextAlignLeft,1,1,1,a,str); } glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(1,1,1,backgroundAlpha*(menu->menuTypeable&&*menu->type)?0.5:1); TexturesSelectTex(FileGetReference(kInterfaceMenuPointerTexture)); glBegin(GL_TRIANGLE_STRIP); float y=menu->cursorShowPos; glTexCoord2d(1,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuPointerSize,y-kInterfaceMenuPointerSize); glTexCoord2d(1,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos+kInterfaceMenuPointerSize,y+kInterfaceMenuPointerSize); glTexCoord2d(0,1); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos-kInterfaceMenuPointerSize,y-kInterfaceMenuPointerSize); glTexCoord2d(0,0); glVertex2f((menu->itemsXPos-0.05)*kScreenXPos-kInterfaceMenuPointerSize,y+kInterfaceMenuPointerSize); glEnd(); glPopAttrib(); if(selection!=-1) TextPrintfToBufferFormatedColored(menu->descPos,0.03,kTextAlignLeft|kTextAutoWrap ,1,1,1,menu->items[selection].flags&kInterfaceMenuItemDisabled?0.45:1 ,menu->items[selection].describtion); TextPrintfToBufferFormatedColoredTilted(Vector(0+sin(menu->easterEggScrollPos*5)*0.1,-menu->easterEggScrollPos),0.05,kTextAlignMiddle,-cos(menu->easterEggScrollPos*5)*0.3,1,0.5,0,1,gEasterEggStrings[menu->easterEggString]); TextPrintBuffer(backgroundAlpha,false); TextClearBuffer(); ScreenBlit(); gTexturesQualityModifier=0; } #define kMenuAnimationTime 0.2 #define kMenuAnimationMaxXZoom 2.5 #define kMenuAnimationMaxYZoom 0.5 void InterfaceTextBufferZoomAnimation(tFileRef background,int in) { float startTime=TimeGetSeconds(); float time=0; while(timeitemsYPos; float minDist=1000; for(int i=0;inumItems;i++) { float dist=fabs(y-menu->items[i].size-mousePos.y); if(mousePos.xitemsXPos) dist+=fabs(mousePos.x-menu->itemsXPos); if(menu->items[i].flags&kInterfaceMenuItemSlider) { if(mousePos.x>menu->itemsXPos+(kInterfaceMenuSlideBarStart+kInterfaceMenuSlideBarWidth)/kScreenXPos) dist+=fabs(mousePos.x-(menu->itemsXPos+(kInterfaceMenuSlideBarStart+kInterfaceMenuSlideBarWidth)/kScreenXPos)); } else if(mousePos.x>menu->itemsXPos+TextWidth(menu->items[i].label,menu->items[i].size)/kScreenXPos) dist+=fabs(mousePos.x-(menu->itemsXPos+TextWidth(menu->items[i].label,menu->items[i].size)/kScreenXPos)); if(distmousePos)) *selection=i; mouseSel=true; } } y-=menu->items[i].lineSpacing; } if(mousePos.x>menu->itemsXPos+kInterfaceMenuSlideBarStart/kScreenXPos&&mousePos.xitemsXPos+(kInterfaceMenuSlideBarStart+kInterfaceMenuSlideBarWidth)/kScreenXPos) mouseBar=(mousePos.x-(menu->itemsXPos+kInterfaceMenuSlideBarStart/kScreenXPos))/(kInterfaceMenuSlideBarWidth/kScreenXPos)+0.08; menu->mousePos=mousePos; */ int key; char ch=GetKeyInput(&key); gLastMenuChar=ch; if(ch||key) gStartIdleTime=TimeGetSeconds(); /* if(key==kInterfaceMouseDown&&mouseSel) if(menu->items[*selection].flags&kInterfaceMenuItemSlider) { if(mouseBar>menu->items[*selection].sliderPos) key=kInterfaceKeyRight; else key=kInterfaceKeyLeft; } else if(menu->items[*selection].flags&kInterfaceMenuItemArrowInput) key=kInterfaceKeyRight; else if(!(menu->items[*selection].flags&kInterfaceMenuItemTypeable)) key=kInterfaceKeyEnter; */ switch(key) { //cursor up/down movement case kInterfaceKeyDown: PlayInterfaceSound(FileGetReference("menu.wav")); (*selection)++; if(*selection>=menu->numItems) *selection=0; break; case kInterfaceKeyUp: PlayInterfaceSound(FileGetReference("menu.wav")); (*selection)--; if(*selection<0) *selection=menu->numItems-1; break; //cursor left/right movement (if enabled) case kInterfaceKeyLeft: if(menu->items[*selection].flags&kInterfaceMenuItemArrowInput&&!(menu->items[*selection].flags&kInterfaceMenuItemDisabled)) { PlayInterfaceSound(FileGetReference("toggle.wav")); *selection|=kInterfaceMenuLeftArrow; if(GetInterfaceKey(kInterfaceKeyEasterEgg)) *selection|=kInterfaceMenuEasterEgg; return true; } break; case kInterfaceKeyRight: if(menu->items[*selection].flags&kInterfaceMenuItemArrowInput&&!(menu->items[*selection].flags&kInterfaceMenuItemDisabled)) { PlayInterfaceSound(FileGetReference("toggle.wav")); *selection|=kInterfaceMenuRightArrow; if(GetInterfaceKey(kInterfaceKeyEasterEgg)) *selection|=kInterfaceMenuEasterEgg; return true; } break; //esc key case kInterfaceKeyDelete: if((menu->items[*selection].flags&kInterfaceMenuItemTypeable)||(menu->menuTypeable)) break; case kInterfaceKeyEsc: PlayInterfaceSound(FileGetReference("esc.wav")); if(menu->menuTypeable&&*menu->type) { *menu->type='\0'; break; } InterfaceMenuZoomAnimation(menu,*selection,false); *selection=kInterfaceMenuEsc; return true; case kInterfaceKeyEasterEgg: if(menu->easterEggEnable) menu->easterEggScrollPos=1.0; menu->easterEggString=RandomInt(0,kNumEasterEggStrings); break; case kInterfaceKeyR: if(menu->easterEggEnable) { InterfaceMenuZoomAnimation(menu,*selection,false); *selection=kInterfaceMenuReplayKey; return true; } break; //enter key case kInterfaceKeyReturn: case kInterfaceKeyEnter: if(menu->menuTypeable&&*menu->type) return true; PlayInterfaceSound(FileGetReference("select.wav")); if(menu->enterAlwaysOK) { InterfaceMenuZoomAnimation(menu,*selection,false); *selection=kInterfaceMenuOK; return true; } if(!(menu->items[*selection].flags&(kInterfaceMenuItemTypeable|kInterfaceMenuItemDisabled|kInterfaceMenuItemArrowInput))) InterfaceMenuZoomAnimation(menu,*selection,false); if(!(menu->items[*selection].flags&kInterfaceMenuItemDisabled)) return true; case kInterfaceKeySpace: if(menu->returnOnSpace) { InterfaceMenuZoomAnimation(menu,*selection,false); *selection|=kInterfaceMenuSpaceFlag; return true; } break; } if(menu->items[*selection].flags&kInterfaceMenuItemTypeable||menu->menuTypeable&&!(menu->menuTypeable==kMenuTypeableReggie&&!gReggieConnected)) { gInterfaceType=true; if(ch) { int len=strlen((menu->items[*selection].flags&kInterfaceMenuItemTypeable)?menu->items[*selection].type:menu->type); if((ch==0x7f||ch==0x08)&&len>0) if(menu->items[*selection].flags&kInterfaceMenuItemTypeable) menu->items[*selection].type[--len]='\0'; else menu->type[--len]='\0'; if(ch>=' '&&ch<='z'&&ch!='%'&&lenitems[*selection].maxTypeLength) { PlayInterfaceSound(FileGetReference("type.wav")); if(menu->items[*selection].flags&kInterfaceMenuItemTypeable) { menu->items[*selection].type[len++]=ch; menu->items[*selection].type[len]='\0'; } else { menu->type[len++]=ch; menu->type[len]='\0'; } } } } else gInterfaceType=menu->items[*selection].flags&kInterfaceMenuItemTypeable; return false; } #define kMenuSelFadeTime 0.2 void InterfaceFadeMenuSelection(tInterfaceMenuDescribtion *menu,float dt,int selection) { for(int i=0;inumItems;i++) { menu->items[i].sel-=dt/kMenuSelFadeTime; if(menu->items[i].sel<0) menu->items[i].sel=0; } if( menu->items[selection].sel<1) menu->items[selection].sel=1; if(menu->cursorShowPos>10) menu->cursorShowPos=menu->cursorPos; if(menu->cursorShowPos>menu->cursorPos) { menu->cursorShowPos-=dt+dt*10*fabs(menu->cursorShowPos-menu->cursorPos); if(menu->cursorShowPoscursorPos) menu->cursorShowPos=menu->cursorPos; } else { menu->cursorShowPos+=dt+dt*10*fabs(menu->cursorShowPos-menu->cursorPos); if(menu->cursorShowPos>menu->cursorPos) menu->cursorShowPos=menu->cursorPos; } } int InterfaceGetUserMenuSelection(tInterfaceMenuDescribtion *menu) { float lastTime=TimeGetSeconds(); int selection=menu->initialSelection; int count=0; do{ if(selection>=menu->numItems||selection<0) selection=0; if(gJoinFlag) if(!menu->joinDisable) { gJoinFlag=false; DirectJoinGame(gJoinHost); } else return kInterfaceMenuEsc; if(!gSystemSuspended||(count++%100==0)) InterfaceMenuRender(menu,selection,1); SystemPoll(false); SystemYieldTime(kMenuFrameTime+lastTime); float time=TimeGetSeconds(); InterfaceFadeMenuSelection(menu,time-lastTime,selection); menu->easterEggScrollPos-=kEasterEggScrollSpeed*(time-lastTime); lastTime=time; if(menu->TimerCallback) { int val=menu->TimerCallback(menu->userData); if(val!=-1) return val; } }while(!InterfaceMenuInput(menu,&selection)); return selection; } #define kScrollTextSize 0.05 int TextPrintFile(tFileRef fileId,float yStart) { float y=yStart; char *fileData=(char*)FileGetDataPtr(fileId); char *filePos=fileData; int fileLenght=FileGetSize(fileId); int linedrawn=false; while(filePos1)a=1; if(y<=1+3*kScrollTextSize&&y>=-1-3*kScrollTextSize) { if(line[0]=='\255'&&line[1]!='#') TextPrintfToBufferFormatedColored(Vector(0,y),kScrollTextSize*5,kTextAlignMiddle,1,1,1,a,line); else TextPrintfToBufferFormatedColored(Vector(0,y),kScrollTextSize,kTextAlignMiddle,1,1,1,a,line); linedrawn=true; } y-=kScrollTextSize*3; } // InterfaceDrawBackground(-1,-1,0,0,0,0,1); InterfaceRenderReplay(NULL,0,NULL); TextPrintBuffer(1,false); TextClearBuffer(); ScreenBlit(); return linedrawn; } void TextScrollFile(tFileRef fileId) { while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc)); float startTime=TimeGetSeconds(); int start=false; int done=false; while(!(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc)||GetInterfaceKey(kInterfaceKeyDelete)||done)) { SystemPoll(false); float time=TimeGetSeconds()-startTime; float y=-1.2+time*0.2; if(!TextPrintFile(fileId,y)){ if(start) done=true; } else start=true; SystemPoll(false); } FlushKeys(); }