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