1 #include "SplitScreen.hh"
2 
3 SplitScreen* active_screen = NULL;
4 
screen_size_callback(int width,int height)5 void GLFWCALL screen_size_callback(int width, int height)
6 {
7     if (active_screen != NULL)
8         active_screen->resize(width, height);
9 }
10 
SplitScreen(int width,int height,int subscreens)11 SplitScreen::SplitScreen(int width, int height, int subscreens)
12     : size(width, height),
13       subscreen_count(subscreens),
14       current(0)
15 {
16     split(subscreens);
17 }
18 
~SplitScreen()19 SplitScreen::~SplitScreen()
20 {
21     if (active_screen == this) {
22         active_screen = NULL;
23         glfwSetWindowSizeCallback(NULL);
24     }
25 }
26 
set_glfw_callback()27 void SplitScreen::set_glfw_callback()
28 {
29     active_screen = this;
30     glfwSetWindowSizeCallback(screen_size_callback);
31 }
32 
split(int subscreens)33 void SplitScreen::split(int subscreens)
34 {
35     subscreen_count = subscreens;
36 
37     cameras.clear();
38     cameras.resize(subscreen_count);
39 
40     resize(size.x, size.y);
41 }
42 
resize(int width,int height)43 void SplitScreen::resize(int width, int height)
44 {
45     size = V2i(width, height);
46 
47     subscreens.clear();
48     point_huds.clear();
49 
50 
51     Box2i box;
52     V2i p1,p2;
53 
54     switch (subscreen_count) {
55     case 1:
56         //+----+
57         //|1111|
58         //|p111|
59         //+----+
60         subscreens.push_back(Box2i(V2i(0,0),
61                                    V2i(0,0) + size));
62 
63 
64 
65         // We hide the points-HUD by moving it out of the screen.
66         p1 = V2i(size.y/12, size.y/12);
67         p2 = V2i(size.y/4, size.y/4);
68         box.makeEmpty();
69         box.extendBy(V2i(0,0) + p1 * V2i(+1,+1));
70         box.extendBy(V2i(0,0) + p2 * V2i(+1,+1));
71         point_huds.push_back(box);
72         break;
73     case 2:
74         //+----+
75         //|p111|
76         //|p222|
77         //+----+
78         subscreens.push_back(Box2i(V2i(0,height/2),
79                                    V2i(0,0) + V2i(width,height)));
80         subscreens.push_back(Box2i(V2i(0,0),
81                                    V2i(0,0) + V2i(width,height/2)));
82 
83         p1 = V2i(size.y/24, size.y/24);
84         p2 = V2i(size.y/4, size.y/4);
85         box.makeEmpty();
86         box.extendBy(V2i(0,height) + p1 * V2i(+1,-1));
87         box.extendBy(V2i(0,height) + p2 * V2i(+1,-1));
88         point_huds.push_back(box);
89         box.makeEmpty();
90         box.extendBy(V2i(0,0) + p1 * V2i(+1,+1));
91         box.extendBy(V2i(0,0) + p2 * V2i(+1,+1));
92         point_huds.push_back(box);
93 
94         break;
95     case 3:
96     case 4:
97         //+----+
98         //|p12p|
99         //|p34p|
100         //+----+
101         subscreens.push_back(Box2i(V2i(0,height/2),
102                                    V2i(0,height) + V2i(size.x/2,0)));
103         subscreens.push_back(Box2i(V2i(width/2,height/2),
104                                    V2i(width/2,height) + V2i(size.x/2,0)));
105         subscreens.push_back(Box2i(V2i(0,0),
106                                    V2i(0,0) + size/2));
107         subscreens.push_back(Box2i(V2i(width/2,0),
108                                    V2i(width/2,0) + size/2));
109 
110 
111 
112         p1 = V2i(size.y/48, size.y/48);
113         p2 = V2i(size.y/8, size.y/8);
114         // 1
115         box.makeEmpty();
116         box.extendBy(V2i(0,height) + p1 * V2i(+1,-1));
117         box.extendBy(V2i(0,height) + p2 * V2i(+1,-1));
118         point_huds.push_back(box);
119         // 2
120         box.makeEmpty();
121         box.extendBy(V2i(width,height) + p1 * V2i(-1,-1));
122         box.extendBy(V2i(width,height) + p2 * V2i(-1,-1));
123         point_huds.push_back(box);
124         // 3
125         box.makeEmpty();
126         box.extendBy(V2i(0,0) + p1 * V2i(+1,+1));
127         box.extendBy(V2i(0,0) + p2 * V2i(+1,+1));
128         point_huds.push_back(box);
129         // 4
130         box.makeEmpty();
131         box.extendBy(V2i(width,0) + p1 * V2i(-1,+1));
132         box.extendBy(V2i(width,0) + p2 * V2i(-1,+1));
133         point_huds.push_back(box);;
134         break;
135 
136     default:
137         cerr << "No known subdivision scheme for " << subscreen_count
138              << " subscreen(s). " << endl;
139         break;
140 
141     }
142 
143     for (int i = 0; i < subscreen_count; i++) {
144         cameras[i].set_aspect((float)subscreens[i].size().x /
145                               (float)subscreens[i].size().y);
146     }
147 }
148 
set_subscreen(int i)149 void SplitScreen::set_subscreen(int i)
150 {
151     current = i;
152 
153     Box2i screen = subscreens[i];
154 
155     glViewport(screen.min.x, screen.min.y,
156                screen.size().x, screen.size().y);
157 }
158 
set_point_hud(int i)159 void SplitScreen::set_point_hud(int i)
160 {
161     current = i;
162 
163     Box2i hud = point_huds[i];
164 
165     glViewport(0, 0,
166                size.x, size.y);
167 
168     glMatrixMode(GL_PROJECTION);
169     glLoadIdentity();
170     glTranslatef(2.0 * hud.center().x/(float)size.x - 1.0,
171                  2.0 * hud.center().y/(float)size.y - 1.0,
172                  0);
173     glScalef(hud.size().x/((float)size.x * 2.0),
174              hud.size().y/((float)size.y * 2.0),
175              1);
176     glMatrixMode(GL_MODELVIEW);
177     glLoadIdentity();
178 }
179 
set_map()180 void SplitScreen::set_map()
181 {
182     V2i start(0,0), end(0,0);
183 
184     int shorter = min(size.x, size.y);
185     int longer = max(size.x, size.y);
186 
187     switch(subscreen_count) {
188     case 1:
189         end = V2i(size.x,longer/4);
190         start = V2i(size.x - longer/4, 0);
191         break;
192     case 2:
193         end = V2i(size.x, (size.y+longer/4)/2);
194         start = V2i(size.x - longer/4, (size.y-longer/4)/2);
195         break;
196     case 3:
197         end = V2i((size.x * 3)/4 + shorter/4,
198                   shorter/2);
199         start = V2i((size.x * 3)/4 - shorter/4,
200                     0);
201         break;
202     case 4:
203         end = size/2 + V2i(shorter,shorter)/4;
204         start = size/2 - V2i(shorter,shorter)/4;
205         break;
206     default:
207         cerr << "No known subdivision scheme for " << subscreen_count
208              << " subscreen(s). " << endl;
209         break;
210     }
211 
212     glViewport(start.x,start.y,(end-start).x, (end-start).y);
213 }
214