1 // 2 // Copyright (C) 2004-2006 Jasmine Langridge, ja-reiko@users.sourceforge.net 3 // 4 // This program is free software; you can redistribute it and/or 5 // modify it under the terms of the GNU General Public License 6 // as published by the Free Software Foundation; either version 2 7 // of the License, or (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 // 18 19 struct joystick_s 20 { 21 SDL_Joystick *sdl_joystick; 22 std::string name; 23 std::vector<float> axis; 24 std::vector<bool> button; 25 std::vector<vec2i> hat; 26 }; 27 28 class PApp 29 { 30 public: 31 32 enum StereoMode 33 { 34 StereoNone, 35 StereoQuadBuffer, 36 StereoRedBlue, 37 StereoRedGreen, 38 StereoRedCyan, 39 StereoYellowBlue 40 }; 41 42 private: 43 44 std::string appname, apptitle; 45 46 SDL_Window *screen; // TODO: rename this to "window" maybe 47 SDL_GLContext context; 48 49 /// Attempts to set fullscreen at native resolution. 50 bool autoVideo = false; 51 52 protected: 53 54 int cx, cy, bpp; 55 HiScore1 best_times; 56 57 private: 58 59 bool fullscr, noframe; 60 bool reqRGB, reqAlpha, reqDepth, reqStencil; 61 bool grabinput; 62 63 StereoMode stereo; 64 float stereoEyeTranslation; 65 66 const uint8* sdl_keymap; 67 int sdl_numkeys; 68 uint8 sdl_mousemap; 69 std::vector<joystick_s> sdl_joy; 70 71 bool exit_requested, screenshot_requested; 72 73 PSSRender *ssrdr; 74 PSSTexture *sstex; 75 PSSEffect *ssfx; 76 PSSModel *ssmod; 77 PSSAudio *ssaud; 78 79 protected: 80 81 // the derived app should keep these up to date 82 vec3f cam_pos; 83 mat44f cam_orimat; 84 vec3f cam_linvel; 85 86 public: 87 88 PApp(const std::string &title = "PGame", const std::string &name = ".pgame"): appname(name)89 appname(name), // for ~/.name 90 apptitle(title), // for window title 91 best_times("/players") 92 { 93 //PUtil::outLog() << "Initialising SDL" << std::endl; 94 const int si = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK); 95 96 if (si < 0) 97 { 98 PUtil::outLog() << "Failed to initialize SDL: " << SDL_GetError() << std::endl; 99 } 100 101 cx = cy = 0; 102 bpp = 0; 103 fullscr = false; 104 noframe = false; 105 exit_requested = false; 106 screenshot_requested = false; 107 reqRGB = reqAlpha = reqDepth = reqStencil = false; 108 stereo = StereoNone; 109 stereoEyeTranslation = 0.0f; 110 grabinput = false; 111 } 112 ~PApp()113 virtual ~PApp() 114 { 115 } 116 117 int run(int argc, char *argv[]); 118 119 public: 120 getWidth()121 int getWidth() const 122 { 123 return cx; 124 } 125 getHeight()126 int getHeight() const 127 { 128 return cy; 129 } 130 getNumJoysticks()131 int getNumJoysticks() 132 { 133 return (sdl_joy.size()); 134 } 135 getJoyNumAxes(int j)136 int getJoyNumAxes(int j) 137 { 138 return (sdl_joy[j].axis.size()); 139 } 140 getJoyNumButtons(int j)141 int getJoyNumButtons(int j) 142 { 143 return (sdl_joy[j].button.size()); 144 } 145 getJoyNumHats(int j)146 int getJoyNumHats(int j) 147 { 148 return (sdl_joy[j].hat.size()); 149 } 150 getJoyAxis(int j,int a)151 float getJoyAxis(int j, int a) 152 { 153 return (sdl_joy[j].axis[a]); 154 } 155 getJoyButton(int j,int b)156 bool getJoyButton(int j, int b) 157 { 158 return (sdl_joy[j].button[b]); 159 } 160 getJoyHat(int j,int h)161 const vec2i &getJoyHat(int j, int h) 162 { 163 return (sdl_joy[j].hat[h]); 164 } 165 getSSRender()166 PSSRender & getSSRender() 167 { 168 return *ssrdr; 169 } 170 getSSTexture()171 PSSTexture & getSSTexture() 172 { 173 return *sstex; 174 } 175 getSSEffect()176 PSSEffect & getSSEffect() 177 { 178 return *ssfx; 179 } 180 getSSModel()181 PSSModel & getSSModel() 182 { 183 return *ssmod; 184 } 185 getSSAudio()186 PSSAudio & getSSAudio() 187 { 188 return *ssaud; 189 } 190 191 protected: 192 keyDown(int key)193 bool keyDown(int key) 194 { 195 return (sdl_keymap[key] != 0); 196 } 197 mouseButtonDown(int bt)198 bool mouseButtonDown(int bt) 199 { 200 return ((sdl_mousemap & SDL_BUTTON(bt)) != 0); 201 } 202 requestExit()203 void requestExit() 204 { 205 exit_requested = true; 206 } 207 saveScreenshot()208 void saveScreenshot() 209 { 210 screenshot_requested = true; 211 } 212 213 void grabMouse(bool grab = true); 214 215 void drawModel(PModel &model); 216 217 void stereoGLProject(float xmin, float xmax, float ymin, float ymax, float znear, float zfar, float zzps, float dist, float eye); 218 void stereoFrustum(float xmin, float xmax, float ymin, float ymax, float znear, float zfar, float zzps, float eye); 219 220 // config stuff 221 222 void setScreenMode(int w, int h, bool fullScreen = false, bool hideFrame = false) 223 { 224 // use automatic video mode 225 if (autoVideo) 226 { 227 SDL_DisplayMode dm; 228 229 if (SDL_GetCurrentDisplayMode(0, &dm) == 0) 230 { 231 cx = dm.w; 232 cy = dm.h; 233 fullscr = fullScreen; 234 noframe = hideFrame; 235 PUtil::outLog() << "Automatic video mode resolution: " << cx << 'x' << cy << std::endl; 236 } 237 else 238 { 239 PUtil::outLog() << "SDL error, SDL_GetCurrentDisplayMode(): " << SDL_GetError() << std::endl; 240 autoVideo = false; 241 } 242 } 243 244 // not written as an `else` branch because `autoVideo` may have 245 // been updated in the case that automatic video mode failed 246 if (!autoVideo) 247 { 248 cx = w; 249 cy = h; 250 fullscr = fullScreen; 251 noframe = hideFrame; 252 } 253 } 254 setScreenBPP(int _bpp)255 void setScreenBPP(int _bpp) 256 { 257 if (autoVideo) 258 return; 259 260 bpp = _bpp; 261 } 262 263 void setScreenModeAutoWindow(); 264 void setScreenModeFastFullScreen(); 265 266 void automaticVideoMode(bool av = false) 267 { 268 autoVideo = av; 269 } 270 271 void requireRGB(bool req = true) 272 { 273 reqRGB = req; 274 } 275 276 void requireAlpha(bool req = true) 277 { 278 reqAlpha = req; 279 } 280 281 void requireDepth(bool req = true) 282 { 283 reqDepth = req; 284 } 285 286 void requireStencil(bool req = true) 287 { 288 reqStencil = req; 289 } 290 setStereoMode(StereoMode mode)291 void setStereoMode(StereoMode mode) 292 { 293 stereo = mode; 294 } 295 setStereoEyeSeperation(float distance)296 void setStereoEyeSeperation(float distance) 297 { 298 stereoEyeTranslation = distance * 0.5f; 299 } 300 301 // callbacks for derived classes 302 303 virtual void config() /* throw (PUserException) */ ; // very light setup/config func 304 virtual void load() /* throw (PUserException) */ ; // main resource loading 305 virtual void unload(); // free resources 306 307 virtual void tick(float delta); 308 virtual void resize(); 309 virtual void render(float eyetranslation); 310 virtual void keyEvent(const SDL_KeyboardEvent &ke); 311 virtual void mouseButtonEvent(const SDL_MouseButtonEvent &mbe); 312 virtual void mouseMoveEvent(int dx, int dy); 313 virtual void cursorMoveEvent(int posx, int posy); 314 virtual void joyButtonEvent(int which, int button, bool down); 315 }; 316 317