fullscreen and mouse grab
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 1 Apr 2023 22:19:28 +0000 (01:19 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 1 Apr 2023 22:19:28 +0000 (01:19 +0300)
GNUmakefile
src/game.c
src/game.h
src/main.c
src/miniglut.c
src/miniglut.h
src/scr_game.c

index f62772a..e794f22 100644 (file)
@@ -10,12 +10,14 @@ def = -DMINIGLUT_USE_LIBC
 inc = -Ilibs -Ilibs/imago -Ilibs/treestor/include -Ilibs/goat3d/include
 libs = libs/unix/imago.a libs/unix/goat3d.a libs/unix/treestor.a
 
-CFLAGS = $(warn) $(dbg) $(opt) $(inc) $(def)
+CFLAGS = $(warn) $(dbg) $(opt) $(inc) $(def) -MMD
 LDFLAGS = $(libs) -lGL -lGLU -lX11 -lm
 
 $(bin): $(obj) libs
        $(CC) -o $@ $(obj) $(LDFLAGS)
 
+-include $(dep)
+
 .c.o:
        $(CC) $(CFLAGS) -c $< -o $@
 
@@ -23,6 +25,10 @@ $(bin): $(obj) libs
 clean:
        rm -f $(obj) $(bin)
 
+.PHONY: cleandep
+cleandep:
+       rm -f $(dep)
+
 .PHONY: libs
 libs:
        $(MAKE) -C libs
index 7dbdef8..a747a62 100644 (file)
@@ -7,8 +7,11 @@
 #include "input.h"
 
 int mouse_x, mouse_y, mouse_state[3];
+int mouse_grabbed;
+unsigned int modkeys;
 int win_width, win_height;
 float win_aspect;
+int fullscr;
 
 struct game_screen *cur_scr;
 
@@ -112,7 +115,15 @@ void game_keyboard(int key, int press)
                switch(key) {
                case 27:
                        game_quit();
-                       break;
+                       return;
+
+               case '\n':
+               case '\r':
+                       if(modkeys & GKEY_MOD_ALT) {
+               case GKEY_F11:
+                               game_fullscreen(-1);
+                       }
+                       return;
                }
        }
 
index 552e06a..d24b5e2 100644 (file)
@@ -13,6 +13,12 @@ enum {
        GKEY_INS
 };
 
+enum {
+       GKEY_MOD_SHIFT  = 1,
+       GKEY_MOD_CTRL   = 4,
+       GKEY_MOD_ALT    = 8
+};
+
 
 struct game_screen {
        const char *name;
@@ -29,8 +35,11 @@ struct game_screen {
 };
 
 extern int mouse_x, mouse_y, mouse_state[3];
+extern int mouse_grabbed;
+extern unsigned int modkeys;
 extern int win_width, win_height;
 extern float win_aspect;
+extern int fullscr;
 
 extern struct game_screen *cur_scr;
 
@@ -49,5 +58,7 @@ void game_chscr(struct game_screen *scr);
 /* defined in main.c */
 void game_swap_buffers(void);
 void game_quit(void);
+void game_fullscreen(int fs);
+void game_grabmouse(int grab);
 
 #endif /* GAME_H_ */
index 859f86b..8743f5b 100644 (file)
@@ -5,13 +5,16 @@
 #include "game.h"
 
 static void idle(void);
+static void reshape(int x, int y);
 static void keydown(unsigned char key, int x, int y);
 static void keyup(unsigned char key, int x, int y);
 static void skeydown(int key, int x, int y);
 static void skeyup(int key, int x, int y);
 static void mouse(int bn, int st, int x, int y);
+static void motion(int x, int y);
 static int translate_skey(int key);
 
+static int warping;
 
 int main(int argc, char **argv)
 {
@@ -22,13 +25,14 @@ int main(int argc, char **argv)
 
        glutDisplayFunc(game_display);
        glutIdleFunc(idle);
-       glutReshapeFunc(game_reshape);
+       glutReshapeFunc(reshape);
        glutKeyboardFunc(keydown);
        glutKeyboardUpFunc(keyup);
        glutSpecialFunc(skeydown);
        glutSpecialUpFunc(skeyup);
        glutMouseFunc(mouse);
-       glutMotionFunc(game_motion);
+       glutMotionFunc(motion);
+       glutPassiveMotionFunc(motion);
 
        if(game_init() == -1) {
                return 1;
@@ -49,14 +53,74 @@ void game_quit(void)
        exit(0);
 }
 
+void game_fullscreen(int fs)
+{
+       static int prev_w, prev_h;
+       static int prev_grab;
+
+       if(fs == -1) {
+               fs = !fullscr;
+       }
+
+       if(fs == fullscr) return;
+
+       if(fs) {
+               prev_w = glutGet(GLUT_WINDOW_WIDTH);
+               prev_h = glutGet(GLUT_WINDOW_HEIGHT);
+               prev_grab = mouse_grabbed;
+               game_grabmouse(1);
+               glutFullScreen();
+       } else {
+               glutReshapeWindow(prev_w, prev_h);
+               if(!prev_grab) {
+                       game_grabmouse(0);
+               }
+       }
+       fullscr = fs;
+}
+
+void game_grabmouse(int grab)
+{
+       static int prev_x, prev_y;
+
+       if(grab == -1) {
+               grab = !mouse_grabbed;
+       }
+
+       if(grab == mouse_grabbed) return;
+
+       if(grab) {
+               warping = 1;
+               prev_x = mouse_x;
+               prev_y = mouse_y;
+               glutWarpPointer(win_width / 2, win_height / 2);
+               glutSetCursor(GLUT_CURSOR_NONE);
+       } else {
+               warping = 1;
+               glutWarpPointer(prev_x, prev_y);
+               glutSetCursor(GLUT_CURSOR_INHERIT);
+       }
+       mouse_grabbed = grab;
+}
+
 
 static void idle(void)
 {
        glutPostRedisplay();
 }
 
+static void reshape(int x, int y)
+{
+       if(fullscr) {
+               warping = 1;
+               glutWarpPointer(x / 2, y / 2);
+       }
+       game_reshape(x, y);
+}
+
 static void keydown(unsigned char key, int x, int y)
 {
+       modkeys = glutGetModifiers();
        game_keyboard(key, 1);
 }
 
@@ -67,8 +131,9 @@ static void keyup(unsigned char key, int x, int y)
 
 static void skeydown(int key, int x, int y)
 {
-       int k = translate_skey(key);
-       if(k >= 0) {
+       int k;
+       modkeys = glutGetModifiers();
+       if((k = translate_skey(key)) >= 0) {
                game_keyboard(k, 1);
        }
 }
@@ -83,9 +148,25 @@ static void skeyup(int key, int x, int y)
 
 static void mouse(int bn, int st, int x, int y)
 {
+       modkeys = glutGetModifiers();
        game_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
 }
 
+static void motion(int x, int y)
+{
+       if(mouse_grabbed) {
+               if(!warping) {
+                       game_motion(x, y);
+                       warping = 1;
+                       glutWarpPointer(win_width / 2, win_height / 2);
+               } else {
+                       warping = 0;
+               }
+       } else {
+               game_motion(x, y);
+       }
+}
+
 static int translate_skey(int key)
 {
        switch(key) {
@@ -109,7 +190,7 @@ static int translate_skey(int key)
                return GKEY_INS;
        default:
                if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
-                       return key - (GLUT_KEY_F1 + GKEY_F1);
+                       return key - GLUT_KEY_F1 + GKEY_F1;
                }
        }
 
index 54838ae..943a3f2 100644 (file)
@@ -832,6 +832,11 @@ void glutSetCursor(int cidx)
        cur_cursor = cidx;
 }
 
+void glutWarpPointer(int x, int y)
+{
+       XWarpPointer(dpy, None, win, 0, 0, 0, 0, x, y);
+}
+
 void glutSetColor(int idx, float r, float g, float b)
 {
        XColor color;
@@ -1319,6 +1324,11 @@ void glutSetCursor(int cidx)
        }
 }
 
+void glutWarpPointer(int x, int y)
+{
+       SetCursorPos(x, y);
+}
+
 void glutSetColor(int idx, float r, float g, float b)
 {
        PALETTEENTRY col;
index 53bb17b..9eebee0 100644 (file)
@@ -162,6 +162,7 @@ void glutSetWindowTitle(const char *title);
 void glutSetIconTitle(const char *title);
 void glutSetCursor(int cursor);
 void glutSetColor(int idx, float r, float g, float b);
+void glutWarpPointer(int x, int y);
 float glutGetColor(int idx, int comp);
 
 void glutIgnoreKeyRepeat(int ignore);
index 98f5d76..4655a90 100644 (file)
@@ -31,7 +31,9 @@ struct game_screen scr_game = {
        gkeyb, gmouse, gmotion
 };
 
-static float cam_theta, cam_phi = 20, cam_dist;
+static float view_mat[16], proj_mat[16];
+
+static float cam_theta, cam_phi, cam_dist;
 static cgm_vec3 cam_pan;
 
 static struct goat3d *gscn;
@@ -126,17 +128,15 @@ static void gupdate(void)
 {
        if(inpstate & INP_MOVE_BITS) {
                cgm_vec3 fwd, right;
-               float theta = cam_theta * M_PI / 180.0f;
-               float phi = cam_phi * M_PI / 180.0f;
 
                float dx = 0, dy = 0;
 
-               fwd.x = -sin(theta) * cos(phi);
-               fwd.y = sin(phi);
-               fwd.z = cos(theta) * cos(phi);
-               right.x = cos(theta);
+               fwd.x = -sin(cam_theta) * cos(cam_phi);
+               fwd.y = sin(cam_phi);
+               fwd.z = cos(cam_theta) * cos(cam_phi);
+               right.x = cos(cam_theta);
                right.y = 0;
-               right.z = sin(theta);
+               right.z = sin(cam_theta);
 
                if(inpstate & INP_FWD_BIT) {
                        dy += 0.1;
@@ -172,12 +172,12 @@ static void gdisplay(void)
                tm_acc -= TSTEP;
        }
 
+       cgm_mtranslation(view_mat, 0, 0, -cam_dist);
+       cgm_mprerotate(view_mat, cam_phi, 1, 0, 0);
+       cgm_mprerotate(view_mat, cam_theta, 0, 1, 0);
+       cgm_mpretranslate(view_mat, cam_pan.x, cam_pan.y, cam_pan.z);
        glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glTranslatef(0, 0, -cam_dist);
-       glRotatef(cam_phi, 1, 0, 0);
-       glRotatef(cam_theta, 0, 1, 0);
-       glTranslatef(cam_pan.x, cam_pan.y, cam_pan.z);
+       glLoadMatrixf(view_mat);
 
        set_light_dir(0, -1, 1, 5);
        set_light_dir(1, 5, 0, 3);
@@ -188,6 +188,9 @@ static void gdisplay(void)
 
 static void greshape(int x, int y)
 {
+       cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.1, 100);
+       glMatrixMode(GL_PROJECTION);
+       glLoadMatrixf(proj_mat);
 }
 
 static void gkeyb(int key, int press)
@@ -204,24 +207,43 @@ static void gkeyb(int key, int press)
                        break;
                }
        }
+
+       if(press) {
+               switch(key) {
+               case '`':
+                       if(!fullscr) {
+                               game_grabmouse(-1);     /* toggle */
+                       }
+                       break;
+               }
+       }
 }
 
 static void gmouse(int bn, int press, int x, int y)
 {
 }
 
+#define PIHALF (M_PI / 2.0)
+
 static void gmotion(int x, int y)
 {
-       int dx = x - mouse_x;
-       int dy = y - mouse_y;
+       int dx, dy;
+
+       if(mouse_grabbed) {
+               dx = x - win_width / 2;
+               dy = y - win_height / 2;
+       } else {
+               dx = x - mouse_x;
+               dy = y - mouse_y;
+       }
 
        if(!(dx | dy)) return;
 
-       if(mouse_state[0]) {
-               cam_theta += dx * 0.5;
-               cam_phi += dy * 0.5;
-               if(cam_phi < -90) cam_phi = -90;
-               if(cam_phi > 90) cam_phi = 90;
+       if(mouse_state[0] || mouse_grabbed) {
+               cam_theta += dx * 0.01;
+               cam_phi += dy * 0.01;
+               if(cam_phi < -PIHALF) cam_phi = -PIHALF;
+               if(cam_phi > PIHALF) cam_phi = PIHALF;
        }
        /*
        if(mouse_state[1]) {