comparison test/testeyes.c @ 4770:cf7976fd3258

Moved the SDL_Eyes test program for shaped windows into the Hg repository and got it building and linking as a test.
author Eli Gottlieb <eligottlieb@gmail.com>
date Mon, 31 May 2010 21:23:06 -0400
parents
children ef8b32ef9793
comparison
equal deleted inserted replaced
4769:83f9b95da263 4770:cf7976fd3258
1 #include <stdlib.h>
2 #include <math.h>
3 #include <SDL_events.h>
4 #include <SDL_rect.h>
5 #include <SDL_pixels.h>
6 #include <SDL_video.h>
7 #include <SDL_shape.h>
8 #include "testeyes_bitmap.h"
9 #include "testeyes_mask_bitmap.h"
10
11 /* The following code for the calculation of pupil positions has been taken and rewritten from the original xeyes. The
12 copyright notice is included as follows, and the code is now under the same license as the rest of this file. */
13 /*
14
15 Copyright (c) 1991 X Consortium
16
17 Permission is hereby granted, free of charge, to any person obtaining
18 a copy of this software and associated documentation files (the
19 "Software"), to deal in the Software without restriction, including
20 without limitation the rights to use, copy, modify, merge, publish,
21 distribute, sublicense, and/or sell copies of the Software, and to
22 permit persons to whom the Software is furnished to do so, subject to
23 the following conditions:
24
25 The above copyright notice and this permission notice shall be included
26 in all copies or substantial portions of the Software.
27
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
32 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
33 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 OTHER DEALINGS IN THE SOFTWARE.
35
36 Except as contained in this notice, the name of the X Consortium shall
37 not be used in advertising or otherwise to promote the sale, use or
38 other dealings in this Software without prior written authorization
39 from the X Consortium.
40
41 */
42 # define NUM_EYES 2
43 # define EYE_X(n) ((n) * 2.0)
44 # define EYE_Y(n) (0.0)
45 # define EYE_THICK (0.175) /* thickness of eye rim */
46 # define EYE_OFFSET (0.1) /* padding between eyes */
47 # define EYE_WIDTH (2.0 - (EYE_THICK + EYE_OFFSET) * 2)
48 # define EYE_HEIGHT EYE_WIDTH
49 # define EYE_HWIDTH (EYE_WIDTH / 2.0)
50 # define EYE_HHEIGHT (EYE_HEIGHT / 2.0)
51 # define BALL_WIDTH (0.3)
52 # define BALL_HEIGHT BALL_WIDTH
53 # define BALL_PAD (0.05)
54 # define BALL_DIST ((EYE_WIDTH - BALL_WIDTH) / 2.0 - BALL_PAD)
55
56 SDL_Point computePupil (int num,SDL_Point mouse) {
57 double dx = mouse.x - EYE_X(num);
58 double dy = mouse.y - EYE_Y(num);
59 double cx = 0.0,cy = 0.0;
60 if(dx == 0 && dy == 0) {
61 cx = EYE_X(num);
62 cy = EYE_Y(num);
63 }
64 else {
65 double angle = atan2((double)dy,(double)dx);
66 double cosa = cos(angle);
67 double sina = sin(angle);
68 double hypotenuse = hypot(EYE_HHEIGHT * cosa, EYE_HWIDTH * sina);
69 double dist = BALL_DIST * hypot((EYE_HWIDTH * EYE_HHEIGHT) * cosa / hypotenuse,
70 (EYE_HWIDTH * EYE_HHEIGHT) * sina / hypotenuse);
71 if(dist > hypot((double)dx,(double)dy)) {
72 cx = dx + EYE_X(num);
73 cy = dy + EYE_Y(num);
74 }
75 else {
76 cx = dist * cosa + EYE_X(num);
77 cy = dist * sina + EYE_Y(num);
78 }
79 }
80 SDL_Point ret = {cx,cy};
81 return ret;
82 }
83
84 /* Here begins the code exclusively and entirely written by Eli Gottlieb in May 2010. */
85 typedef struct {
86 SDL_Rect left;
87 SDL_Rect right;
88 } Pupil_Pair;
89 typedef struct {
90 SDL_Point left;
91 SDL_Point right;
92 } Pupil_Points;
93
94 Pupil_Pair compute_pupil_positions(SDL_Point target) {
95 Pupil_Pair result;
96 Pupil_Points points;
97 points.left = computePupil(0,target);
98 points.right = computePupil(1,target);
99 result.left.x = points.left.x - BALL_WIDTH / 2.0;
100 result.left.y = points.left.y - BALL_HEIGHT / 2.0;
101 result.right.x = points.right.x - BALL_WIDTH / 2.0;
102 result.right.y = points.right.y - BALL_HEIGHT / 2.0;
103 result.left.w = result.right.w = BALL_WIDTH;
104 result.left.h = result.left.w = BALL_HEIGHT;
105 return result;
106 }
107
108 void render_eyes(SDL_Window *window,SDL_Texture *eyes_texture,Pupil_Pair pupils) {
109 SDL_SelectRenderer(window);
110
111 //Clear render-target to blue.
112 SDL_SetRenderDrawColor(0x00,0x00,0xff,0xff);
113 SDL_RenderClear();
114
115 //Render the whites of the eyes.
116 SDL_Rect srcdestrect = {0,0,eyes_width,eyes_height};
117 SDL_RenderCopy(eyes_texture,&srcdestrect,&srcdestrect);
118
119 //Render the pupils.
120 SDL_SetRenderDrawColor(0x00,0x00,0x00,0xff);
121 const SDL_Rect eyes[2] = {pupils.left,pupils.right};
122 SDL_RenderFillRects((const SDL_Rect**)&eyes,2);
123
124 SDL_RenderPresent();
125 }
126
127 int main(int argc,char** argv) {
128 if(SDL_VideoInit(NULL,0) == -1) {
129 printf("Could not initialize SDL video.\n");
130 exit(-1);
131 }
132
133 SDL_Window *window = SDL_CreateShapedWindow("Big Brother is watching you.",eyes_x_hot,eyes_y_hot,eyes_width,eyes_height,SDL_WINDOW_RESIZABLE);
134 if(window == NULL) {
135 SDL_VideoQuit();
136 printf("Could not create shaped window for eyes.\n");
137 exit(-2);
138 }
139 if(SDL_CreateRenderer(window,-1,SDL_RENDERER_PRESENTFLIP2) == -1) {
140 SDL_DestroyWindow(window);
141 SDL_VideoQuit();
142 printf("Could not create rendering context for SDL_Eyes window.\n");
143 exit(-3);
144 }
145
146 SDL_Color bnw_palette[2] = {{0,0,0,0},{255,255,255,255}};
147 SDL_Texture *eyes_texture = SDL_CreateTexture(SDL_PIXELFORMAT_INDEX1LSB,SDL_TEXTUREACCESS_STREAMING,eyes_width,eyes_height);
148 if(eyes_texture == NULL) {
149 SDL_DestroyRenderer(window);
150 SDL_DestroyWindow(window);
151 SDL_VideoQuit();
152 printf("Could not create eyes texture.\n");
153 exit(-4);
154 }
155 SDL_SetTexturePalette(eyes_texture,bnw_palette,0,2);
156
157 void *pixels = NULL;
158 int pitch = 0;
159 SDL_Rect rect = {0,0,eyes_width,eyes_height};
160 SDL_LockTexture(eyes_texture,&rect,1,&pixels,&pitch);
161 for(int row = 0;row<eyes_height;row++)
162 memcpy(pixels+pitch*row,eyes_bits+(eyes_width/8)*row,eyes_width/8);
163 SDL_UnlockTexture(eyes_texture);
164
165 SDL_Texture *mask_texture = SDL_CreateTexture(SDL_PIXELFORMAT_INDEX1LSB,SDL_TEXTUREACCESS_STREAMING,eyesmask_width,eyesmask_height);
166 if(mask_texture == NULL) {
167 SDL_DestroyTexture(eyes_texture);
168 SDL_DestroyRenderer(window);
169 SDL_DestroyWindow(window);
170 SDL_VideoQuit();
171 printf("Could not create shape mask texture.\n");
172 exit(-5);
173 }
174 SDL_SetTexturePalette(mask_texture,bnw_palette,0,2);
175
176 rect.x = rect.y = 0;
177 rect.w = eyesmask_width;
178 rect.h = eyesmask_height;
179 SDL_LockTexture(mask_texture,&rect,1,&pixels,&pitch);
180 for(int row = 0;row<eyesmask_height;row++)
181 memcpy(pixels+pitch*row,eyesmask_bits+(eyesmask_width/8)*row,eyesmask_width/8);
182 SDL_UnlockTexture(mask_texture);
183
184 SDL_SelectShapeRenderer(window);
185 SDL_RenderCopy(mask_texture,&rect,&rect);
186 SDL_RenderPresent();
187
188 SDL_Event event;
189 int event_pending = 0;
190 event_pending = SDL_PollEvent(&event);
191 SDL_Point mouse_position;
192 Pupil_Pair pupil_positions;
193 SDL_SelectMouse(0);
194 SDL_GetMouseState(&mouse_position.x,&mouse_position.y);
195 pupil_positions = compute_pupil_positions(mouse_position);
196 while(event.type != SDL_QUIT) {
197 if(event.type == SDL_MOUSEMOTION) {
198 mouse_position.x = event.motion.x;
199 mouse_position.y = event.motion.y;
200 pupil_positions = compute_pupil_positions(mouse_position);
201 }
202 render_eyes(window,eyes_texture,pupil_positions);
203 event_pending = SDL_PollEvent(&event);
204 }
205
206 //Call SDL_VideoQuit() before quitting.
207 SDL_VideoQuit();
208 }