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