1 // ----------------------------------------------------------
2 //
3 // Copyright (C) 2002 Brad Wasson <bard@systemtoolbox.com>
4 //
5 // This file is part of 3ddesktop.
6 //
7 // 3ddesktop is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11 //
12 // 3ddesktop is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with 3ddesktop; see the file COPYING. If not, write to
19 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h> // for memset
25
26 using namespace std;
27 #include <stack>
28
29 #include "3ddesk.h"
30 #include "arrange.hpp"
31 #include "util.h"
32
33 #define LINEAR_MOVE_TYPE Movement::MOVE_TYPE_WACK
34 #define CYLINDER_MOVE_TYPE Movement::MOVE_TYPE_WACK
35 #define VIEWMASTER_MOVE_TYPE Movement::MOVE_TYPE_WACK
36 #define CAROUSEL_MOVE_TYPE Movement::MOVE_TYPE_WACK
37
38 // ==============================================================
39 // Arrangement - abstract base class
40 // ==============================================================
41
Arrangement(FaceSet * fs,Config * c)42 Arrangement::Arrangement (FaceSet *fs, Config *c)
43 {
44 // defaults
45 z_offset_distance = 7.0;
46 face_list = glGenLists(1);
47 move_type = Movement::MOVE_TYPE_WACK;
48
49 cfg = c;
50 face_set = fs;
51
52 msgout(DEBUG, "Arrangement constructor\n");
53 //memset(faces, 0, sizeof(faces));
54 }
55
~Arrangement()56 Arrangement::~Arrangement ()
57 {
58 glDeleteLists(face_list, 1);
59 }
60
set_active(int i)61 void Arrangement::set_active (int i)
62 {
63 if (face_set)
64 face_set->set_active(i);
65 }
66
set_current_face(int col,int row)67 void Arrangement::set_current_face (int col, int row)
68 {
69 current_col = col;
70 current_row = row;
71 current_face = col + (row * n_columns);
72 }
73
get_current_column(void)74 int Arrangement::get_current_column(void)
75 {
76 return current_col;
77 }
78
get_current_row(void)79 int Arrangement::get_current_row(void)
80 {
81 return current_row;
82 }
83
get_number_of_columns(void)84 int Arrangement::get_number_of_columns(void)
85 {
86 return n_columns;
87 }
88
get_number_of_rows(void)89 int Arrangement::get_number_of_rows(void)
90 {
91 return n_rows;
92 }
93
get_current_z_offset(void)94 float Arrangement::get_current_z_offset(void)
95 {
96 return z_offset;
97 }
98
set_z_offset_distance(float zod)99 void Arrangement::set_z_offset_distance(float zod)
100 {
101 z_offset_distance = zod;
102 }
103
cant_exit_in_goto(void)104 int Arrangement::cant_exit_in_goto(void)
105 {
106 // if not zooming the it is true that we cant exit while in goto
107 return !cfg->options->entry_exit_movement;
108 }
109
goto_up(void)110 void Arrangement::goto_up(void)
111 {
112 goto_right();
113 }
goto_down(void)114 void Arrangement::goto_down(void)
115 {
116 goto_left();
117 }
118
goto_right(void)119 void Arrangement::goto_right(void)
120 {
121 current_col++;
122 if (current_col == n_columns)
123 current_col = 0; // cycle around
124
125 if (goto_face_mv.at_destination()) {
126 goto_face_mv.init (&goto_face_val,
127 goto_face_val, goto_face_val - per_face_change,
128 cfg->options->face_change_steps, move_type);
129 } else {
130 goto_face_mv.init (&goto_face_val,
131 goto_face_val, goto_face_mv.destination() - per_face_change,
132 cfg->options->face_change_steps, move_type);
133 }
134 }
135
goto_left(void)136 void Arrangement::goto_left(void)
137 {
138 if (current_col == 0)
139 current_col = n_columns - 1; // cycle around
140 else
141 current_col--;
142
143 if (goto_face_mv.at_destination()) {
144 goto_face_mv.init (&goto_face_val,
145 goto_face_val, goto_face_val + per_face_change,
146 cfg->options->face_change_steps, move_type);
147 } else {
148 goto_face_mv.init (&goto_face_val,
149 goto_face_val, goto_face_mv.destination() + per_face_change,
150 cfg->options->face_change_steps, move_type);
151 }
152 }
153
154 // this function "unrolls" a face to col and row "coords" it does not
155 // check bounds
goto_face(int face)156 float Arrangement::goto_face (int face)
157 {
158 int col = face % n_columns;
159 int row = face / n_columns;
160
161 return goto_face(col, row);
162 }
163
goto_face(int col,int row)164 float Arrangement::goto_face (int col, int row)
165 {
166 desktop_coords_t g;
167
168 g.column = col;
169 g.row = row;
170
171 return goto_face(g);
172 }
173
174 // this goto face assumes a circular arrangement
175 // overload for other
goto_face(desktop_coords_t dest)176 float Arrangement::goto_face (desktop_coords_t dest)
177 {
178 if (dest.column < 0
179 || dest.column >= n_columns
180 || dest.row < 0
181 || dest.row >= n_rows)
182 {
183 //msgout (DEBUG, "row / col goto out of range (%u x %u)\n",
184 // dest.column, dest.row);
185 return 0;
186 }
187
188 int newface = dest.column + (dest.row * n_columns);
189
190 int current = current_col + (current_row * n_columns);
191
192 int number = n_columns * n_rows;
193
194 float new_rot;
195
196 // eeek! figure out the shortest distance to the new face... there
197 // must be a more elegant way! but for now this works...
198 if (newface > current) {
199 if ( (newface - current) <
200 ((current + number) - newface) )
201 {
202 // normal case
203 new_rot = -per_face_change * (newface - current);
204 } else {
205 // "wrapped"
206 new_rot = per_face_change * ((current + number) - newface);
207 }
208 } else {
209 // newface < current
210
211 if ( (current - newface) >
212 ((newface + number) - current) )
213 {
214 // "wrapped"
215 new_rot = -per_face_change * ((newface + number) - current);
216 } else {
217 // normal case
218 new_rot = per_face_change * (current - newface);
219 }
220 }
221
222 if (goto_face_mv.at_destination())
223 goto_face_mv.init (&goto_face_val, goto_face_val,
224 goto_face_val + new_rot,
225 cfg->options->face_change_steps, move_type);
226 else
227 goto_face_mv.init (&goto_face_val, goto_face_val,
228 goto_face_mv.destination() + new_rot,
229 cfg->options->face_change_steps, move_type);
230
231 current_col = dest.column; //newface;
232 current_row = dest.row;
233 current_face = newface;
234
235 return cfg->options->face_change_steps;
236 }
237
in_goto(void)238 int Arrangement::in_goto (void)
239 {
240 return !goto_face_mv.at_destination();
241 }
242
243
goto_random_face(void)244 void Arrangement::goto_random_face(void)
245 {
246 int which_one;
247
248 do {
249 which_one = get_randomi (0, (n_columns * n_rows) - 1);
250 } while (which_one == (current_col + (current_row * n_rows)));
251
252 goto_face (which_one);
253 }
254
255
entry_movement_start(void)256 void Arrangement::entry_movement_start(void)
257 {
258 if (!cfg->options->entry_exit_movement)
259 return;
260
261 z_off_mv.init (&z_offset,
262 z_offset_close, get_distant_z_offset(),
263 cfg->options->zoom_steps,
264 Movement::MOVE_TYPE_SMOOTH);
265 }
266
exit_movement_start(void)267 void Arrangement::exit_movement_start(void)
268 {
269 if (!cfg->options->entry_exit_movement)
270 return;
271
272 z_off_mv.init(&z_offset,
273 z_offset, z_offset_close,
274 cfg->options->zoom_steps, Movement::MOVE_TYPE_WACK);
275 }
276
exit_movement_cancel(void)277 void Arrangement::exit_movement_cancel(void)
278 {
279 if (!cfg->options->entry_exit_movement)
280 return;
281
282 z_off_mv.init (&z_offset,
283 z_offset, get_distant_z_offset(),
284 cfg->options->zoom_steps,
285 Movement::MOVE_TYPE_SMOOTH);
286 }
287
is_entry_movement_done(void)288 int Arrangement::is_entry_movement_done(void)
289 {
290 return (!cfg->options->entry_exit_movement || z_off_mv.at_destination());
291 }
292
is_exit_movement_done(void)293 int Arrangement::is_exit_movement_done(void)
294 {
295 return (!cfg->options->entry_exit_movement || z_off_mv.at_destination());
296 }
297
entry_exit_move(void)298 void Arrangement::entry_exit_move(void)
299 {
300 if (!cfg->options->entry_exit_movement)
301 return;
302
303 z_off_mv.change_a_bit();
304 }
305
set_transparency(float t)306 void Arrangement::set_transparency (float t)
307 {
308 face_set->set_transparency (t);
309 }
310
render()311 void Arrangement::render()
312 {
313 face_set->render_all(current_face);
314 //face_set->render_all();
315 }
316
317 // sacrifice the call list for the pretty transparency... :/
318
319 //void Arrangement::render()
320 //{
321 // glCallList(face_list);
322 //}
323
make_display_list(void)324 void Arrangement::make_display_list(void)
325 {
326 glMatrixMode(GL_MODELVIEW);
327
328 glNewList(face_list,GL_COMPILE);
329
330 face_set->render_all();
331
332 glEndList();
333 }
334
position_lighting(void)335 void Arrangement::position_lighting(void)
336 {
337 // For most arrangements (carousel, cylinder, priceisright,
338 // viewmaster) we want to move the camera out away from the faces
339 // but not rotate around to the current face (goto_face_val) as
340 // that would spin the lighting around.
341 camera->Look();
342 }
343
344
allow_blending(void)345 int Arrangement::allow_blending(void)
346 {
347 return true;
348 }
349
350 // ==============================================================
351 // CarouselArrangement
352 // ==============================================================
353
CarouselArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)354 CarouselArrangement::CarouselArrangement(VDesktops &vdesks,
355 float fw, float fh,
356 FaceSet *fs,
357 Config *c,
358 Camera *cam)
359
360 : Arrangement (fs, c)
361 {
362 X_Rot = 0;
363 x_rot_final = 15.0;
364
365 face_width = fw;
366 face_height = fh;
367
368 camera = cam;
369
370 calculate_faces(vdesks);
371
372 goto_face_mv.disable();
373 }
374
calculate_faces(VDesktops & vdesks)375 void CarouselArrangement::calculate_faces(VDesktops & vdesks)
376 {
377
378 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
379 &n_columns, &n_rows);
380
381 // current_face becomes the unrolled current face
382 current_face = current_col + (current_row * n_columns);
383
384 // n_faces becomes the total number of desktops
385 n_faces = n_columns * n_rows;
386
387 side_angle = 360.0 / (float)n_faces;
388
389 per_face_change = side_angle;
390
391 goto_face_val = 360 - (side_angle * current_face);
392
393 // make this value up - give us space between each face
394 float circum = face_width * 1.5 * n_faces;
395
396 // this is a class value that we keep
397 radius = circum / (2.0 * PI);
398
399 // angle in radians of right triangle angle from camera to face
400 float my_angle = ((FOV / 2.0) * PI) / 180.0;
401
402 float half_face_height = face_height / 2.0;
403 float half_face_width = face_width / 2.0;
404
405 // find distance from camera to face to show whole face then add
406 // radius to it. get_base_z_offset returns radius
407 z_offset_close = z_offset = -(float)(half_face_height / tan(my_angle) +
408 get_base_z_offset());
409
410
411 // msgout (DEBUG, "_________ rad %f my_angle %f circum %f z_off %f z_off_c %f fw %f fh %f\n",
412 // radius, my_angle, circum, z_offset, z_offset_close,
413 // face_width, face_height);
414
415 int i;
416
417 Point tl,tr,bl,br;
418
419 for (i = 0; i < n_faces; i++) {
420
421 tl.set (-half_face_width, half_face_height, 0);
422 tr.set ( half_face_width, half_face_height, 0);
423 bl.set (-half_face_width, -half_face_height, 0);
424 br.set ( half_face_width, -half_face_height, 0);
425
426 translate (tl.v, 0, 0, radius);
427 rotate_y (tl.v, side_angle * i);
428
429 translate (tr.v, 0, 0, radius);
430 rotate_y (tr.v, side_angle * i);
431
432 translate (bl.v, 0, 0, radius);
433 rotate_y (bl.v, side_angle * i);
434
435 translate (br.v, 0, 0, radius);
436 rotate_y (br.v, side_angle * i);
437
438 // msgout (DEBUG, "[%i] = %f, %f, %f\n", i, tl.v[0], tl.v[1], tl.v[2]);
439
440
441 // the palindromic serendipity of this rocks!
442 face_set->set_face(i, tl, tr, bl, br);
443
444 #if 0
445 msgout(DEBUG, "[%i] X tl=%f, tr=%f, br=%f\n", i,
446 face_set->topleft.v[0], face_set->topright.v[0], face_set->bottomright.v[0]);
447 msgout(DEBUG, "[%i] Y tl=%f, tr=%f, br=%f\n", i,
448 face_set->topleft.v[1], face_set->topright.v[1], face_set->bottomright.v[1]);
449 msgout(DEBUG, "[%i] Z tl=%f, tr=%f, br=%f\n", i,
450 face_set->topleft.v[2], face_set->topright.v[2], face_set->bottomright.v[2]);
451
452 msgout(DEBUG, "[%i] normal = %f, %f, %f\n\n", i,
453 f->normal.v[0], f->normal.v[1], f->normal.v[2]);
454 #endif
455
456 }
457
458 //make_display_list();
459 }
460
get_type()461 int CarouselArrangement::get_type ()
462 {
463 return FACE_TYPE_CAROUSEL;
464 }
465
set_current_face(int c,int r)466 void CarouselArrangement::set_current_face (int c, int r)
467 {
468 current_face = c + (r * n_columns);
469 current_col = c;
470 current_row = r;
471 goto_face_val = 360 - (side_angle * current_face);
472 goto_face_mv.disable();
473 }
474
get_distant_z_offset(void)475 float CarouselArrangement::get_distant_z_offset(void)
476 {
477 return -(z_offset_distance + get_base_z_offset());
478 }
479
get_base_z_offset(void)480 float CarouselArrangement::get_base_z_offset(void)
481 {
482 return (radius);
483 }
484
485
do_movement(void)486 void CarouselArrangement::do_movement(void)
487 {
488 if (!goto_face_mv.at_destination())
489 goto_face_mv.change_a_bit ();
490 else
491 clamp_degrees(&goto_face_val);
492
493 }
494
position_faces(void)495 void CarouselArrangement::position_faces(void)
496 {
497 //glTranslatef(0.0f,0.0f, z_offset);
498 camera->position.z = -z_offset;
499
500 //glRotatef(X_Rot, 1.0f, 0.0f, 0.0f);
501 extern Vector zero; // rotate around the center (0,0,0)
502 camera->RotateAroundPoint(zero, -deg_to_rad(X_Rot), 1, 0, 0);
503
504 camera->Look();
505
506 glRotatef(goto_face_val, 0.0f, 1.0f, 0.0f);
507 //camera->RotateAroundPoint(center, -deg_to_rad(goto_face_val), 0, 1, 0);
508 }
509
goto_random_face(void)510 void CarouselArrangement::goto_random_face(void)
511 {
512 int which_one;
513
514 do {
515 which_one = get_randomi (0, (n_columns * n_rows) - 1);
516 } while (which_one == (current_col + (current_row * n_rows)));
517
518 current_face = which_one;
519
520 goto_face (which_one);
521 }
522
goto_right(void)523 void CarouselArrangement::goto_right(void)
524 {
525 current_face++;
526 if (current_face == n_faces)
527 current_face = 0; // cycle around
528
529 // we are "unrolling" rows and columns so map the linear
530 // "current_face" back to rows and columns
531 current_col = current_face % n_columns;
532 current_row = current_face / n_columns;
533
534 if (goto_face_mv.at_destination()) {
535 goto_face_mv.init (&goto_face_val,
536 goto_face_val, goto_face_val - per_face_change,
537 cfg->options->face_change_steps, move_type);
538 } else {
539 goto_face_mv.init (&goto_face_val,
540 goto_face_val, goto_face_mv.destination() - per_face_change,
541 cfg->options->face_change_steps, move_type);
542 }
543 }
544
goto_left(void)545 void CarouselArrangement::goto_left(void)
546 {
547 if (current_face == 0)
548 current_face = n_faces - 1; // cycle around
549 else
550 current_face--;
551
552 // we are "unrolling" rows and columns so map the linear
553 // "current_face" back to rows and columns
554 current_col = current_face % n_columns;
555 current_row = current_face / n_columns;
556
557 if (goto_face_mv.at_destination()) {
558 goto_face_mv.init (&goto_face_val,
559 goto_face_val, goto_face_val + per_face_change,
560 cfg->options->face_change_steps, move_type);
561 } else {
562 goto_face_mv.init (&goto_face_val,
563 goto_face_val, goto_face_mv.destination() + per_face_change,
564 cfg->options->face_change_steps, move_type);
565 }
566 }
567
entry_movement_start(void)568 void CarouselArrangement::entry_movement_start(void)
569 {
570 if (!cfg->options->entry_exit_movement)
571 return;
572
573 x_rot_mv.init (&X_Rot,
574 0.0, x_rot_final,
575 cfg->options->zoom_steps,
576 Movement::MOVE_TYPE_SMOOTH);
577 Arrangement::entry_movement_start();
578 }
579
exit_movement_start(void)580 void CarouselArrangement::exit_movement_start(void)
581 {
582 if (!cfg->options->entry_exit_movement)
583 return;
584
585 x_rot_mv.init(&X_Rot,
586 X_Rot, 0.0,
587 cfg->options->zoom_steps,
588 Movement::MOVE_TYPE_WACK);
589 Arrangement::exit_movement_start();
590 }
591
exit_movement_cancel(void)592 void CarouselArrangement::exit_movement_cancel(void)
593 {
594 if (!cfg->options->entry_exit_movement)
595 return;
596
597 x_rot_mv.init(&X_Rot,
598 X_Rot, x_rot_final,
599 cfg->options->zoom_steps,
600 Movement::MOVE_TYPE_WACK);
601 Arrangement::exit_movement_cancel();
602 }
603
entry_exit_move(void)604 void CarouselArrangement::entry_exit_move(void)
605 {
606 if (!cfg->options->entry_exit_movement)
607 return;
608
609 x_rot_mv.change_a_bit();
610 Arrangement::entry_exit_move();
611 }
612
613
614 #if !defined (ONE_ARRANGEMENT_ONLY)
615
616
617 // ==============================================================
618 // CylinderArrangement
619 // ==============================================================
620
621
CylinderArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)622 CylinderArrangement::CylinderArrangement(VDesktops &vdesks,
623 float fw, float fh,
624 FaceSet *fs,
625 Config *c,
626 Camera *cam)
627 : Arrangement (fs, c)
628 {
629 two_face_gap = 3;
630
631 z_offset_distance = 5.0;
632
633 X_Rot = 0.0;
634 x_rot_final = 15.0;
635
636 face_width = fw;
637 face_height = fh;
638
639 camera = cam;
640
641 calculate_faces(vdesks);
642
643 goto_face_mv.disable();
644 }
645
calculate_faces(VDesktops & vdesks)646 void CylinderArrangement::calculate_faces(VDesktops & vdesks)
647 {
648 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
649 &n_columns, &n_rows);
650
651 // current_face becomes the unrolled current face
652 current_face = current_col + (current_row * n_columns);
653
654 // n_faces becomes the total number of desktops
655 n_faces = n_columns * n_rows;
656
657 side_angle = 360.0 / (float)n_faces;
658 per_face_change = side_angle;
659
660 goto_face_val = 360 - (side_angle * current_face);
661
662
663 float my_angle = ((FOV / 2.0) * PI) / 180.0;
664
665 // get_base_z_offset returns radius
666 z_offset_close = z_offset = -(float)((face_height/2.0) / tan(my_angle) +
667 get_base_z_offset());
668
669 int i;
670 float half_face_height = face_height / 2.0;
671 float half_face_width = face_width / 2.0;
672
673 Point tl,tr,bl,br;
674
675 if (n_faces == 2) {
676
677 // 2 faces really messes up becase the faces sandwhich
678 // together and you can't see one of the textures so special
679 // case it and move them apart
680
681 tl.set (-half_face_width, half_face_height, two_face_gap);
682 tr.set ( half_face_width, half_face_height, two_face_gap);
683 bl.set (-half_face_width, -half_face_height, two_face_gap);
684 br.set ( half_face_width, -half_face_height, two_face_gap);
685
686 face_set->set_face (0, tl, tr, bl, br);
687
688 tl.set ( half_face_width, half_face_height, -two_face_gap);
689 tr.set (-half_face_width, half_face_height, -two_face_gap);
690 bl.set ( half_face_width, -half_face_height, -two_face_gap);
691 br.set (-half_face_width, -half_face_height, -two_face_gap);
692
693 face_set->set_face (1, tl, tr, bl, br);
694
695 } else {
696 polypoints_t pp;
697
698 calculate_polypoints (n_faces, face_width, &pp);
699 for (i = 0; i < n_faces; i++) {
700 // translate the values calculated for a n-face polygon in
701 // a x-y coord system to the 3d x-y-z coords. we don't
702 // need y because the up and down (y-axis) is always
703 // either half_face_height or -half_face_height
704
705 //msgout(DEBUG, "%u:: x=%lf y=%lf\n", i, pp.x[i], pp.y[i]);
706
707 tl.set( pp.x[i], half_face_height, -pp.y[i]);
708 bl.set( pp.x[i], -half_face_height, -pp.y[i]);
709
710 if (i == n_faces - 1) {
711 tr.set( pp.x[0], half_face_height, -pp.y[0]);
712 br.set( pp.x[0], -half_face_height, -pp.y[0]);
713 } else {
714 tr.set( pp.x[i+1], half_face_height, -pp.y[i+1]);
715 br.set( pp.x[i+1], -half_face_height, -pp.y[i+1]);
716 }
717
718 face_set->set_face (i, tl, tr, bl, br);
719
720 }
721 }
722
723 //make_display_list();
724
725 }
726
get_type()727 int CylinderArrangement::get_type ()
728 {
729 return FACE_TYPE_CYLINDER;
730 }
731
set_current_face(int c,int r)732 void CylinderArrangement::set_current_face (int c, int r)
733 {
734 current_col = c;
735 current_row = r;
736 current_face = c + (r * n_columns);
737 goto_face_val = 360 - (side_angle * current_face);
738 goto_face_mv.disable();
739 }
740
get_distant_z_offset(void)741 float CylinderArrangement::get_distant_z_offset(void)
742 {
743 return -(z_offset_distance + get_base_z_offset());
744 }
745
get_base_z_offset(void)746 float CylinderArrangement::get_base_z_offset(void)
747 {
748 if (n_faces == 2) {
749 return two_face_gap;
750 } else {
751 return ((face_width/2.0) / tan (deg_to_rad(side_angle/2.0)));
752 }
753 }
754
755 // this has to by overridden because of the 'current_face' variable
756 // which is private to this class
goto_random_face(void)757 void CylinderArrangement::goto_random_face(void)
758 {
759 int which_one;
760
761 do {
762 which_one = get_randomi (0, (n_columns * n_rows) - 1);
763 } while (which_one == (current_col + (current_row * n_rows)));
764
765 current_face = which_one;
766
767 goto_face (which_one);
768 }
769
goto_right(void)770 void CylinderArrangement::goto_right(void)
771 {
772 current_face++;
773 if (current_face == n_faces)
774 current_face = 0; // cycle around
775
776 // we are "unrolling" rows and columns so map the linear
777 // "current_face" back to rows and columns
778 current_col = current_face % n_columns;
779 current_row = current_face / n_columns;
780
781 if (goto_face_mv.at_destination()) {
782 goto_face_mv.init (&goto_face_val,
783 goto_face_val, goto_face_val - per_face_change,
784 cfg->options->face_change_steps, move_type);
785 } else {
786 goto_face_mv.init (&goto_face_val,
787 goto_face_val, goto_face_mv.destination() - per_face_change,
788 cfg->options->face_change_steps, move_type);
789 }
790 }
791
goto_left(void)792 void CylinderArrangement::goto_left(void)
793 {
794 if (current_face == 0)
795 current_face = n_faces - 1; // cycle around
796 else
797 current_face--;
798
799 // we are "unrolling" rows and columns so map the linear
800 // "current_face" back to rows and columns
801 current_col = current_face % n_columns;
802 current_row = current_face / n_columns;
803
804 if (goto_face_mv.at_destination()) {
805 goto_face_mv.init (&goto_face_val,
806 goto_face_val, goto_face_val + per_face_change,
807 cfg->options->face_change_steps, move_type);
808 } else {
809 goto_face_mv.init (&goto_face_val,
810 goto_face_val, goto_face_mv.destination() + per_face_change,
811 cfg->options->face_change_steps, move_type);
812 }
813 }
814
815
do_movement(void)816 void CylinderArrangement::do_movement(void)
817 {
818 if (!goto_face_mv.at_destination())
819 goto_face_mv.change_a_bit ();
820 else
821 clamp_degrees(&goto_face_val);
822 }
823
position_faces(void)824 void CylinderArrangement::position_faces(void)
825 {
826 //glTranslatef(0.0f,0.0f, z_offset);
827 camera->position.z = -z_offset;
828
829 //glRotatef(X_Rot, 1.0f, 0.0f, 0.0f);
830 extern Vector zero; // rotate around the center (0,0,0)
831 camera->RotateAroundPoint(zero, -deg_to_rad(X_Rot), 1, 0, 0);
832
833 camera->Look();
834
835 glRotatef(goto_face_val, 0.0f, 1.0f, 0.0f);
836 }
837
entry_movement_start(void)838 void CylinderArrangement::entry_movement_start(void)
839 {
840 //if (!cfg->options->entry_exit_movement)
841 // return;
842
843 x_rot_mv.init (&X_Rot,
844 0.0, x_rot_final,
845 cfg->options->zoom_steps,
846 Movement::MOVE_TYPE_SMOOTH);
847 Arrangement::entry_movement_start();
848 }
849
exit_movement_start(void)850 void CylinderArrangement::exit_movement_start(void)
851 {
852 //if (!cfg->options->entry_exit_movement)
853 // return;
854
855 x_rot_mv.init(&X_Rot,
856 X_Rot, 0.0,
857 cfg->options->zoom_steps,
858 Movement::MOVE_TYPE_WACK);
859 Arrangement::exit_movement_start();
860 }
861
exit_movement_cancel(void)862 void CylinderArrangement::exit_movement_cancel(void)
863 {
864 //if (!cfg->options->entry_exit_movement)
865 // return;
866
867 x_rot_mv.init(&X_Rot,
868 X_Rot, x_rot_final,
869 cfg->options->zoom_steps,
870 Movement::MOVE_TYPE_WACK);
871 Arrangement::exit_movement_cancel();
872 }
873
entry_exit_move(void)874 void CylinderArrangement::entry_exit_move(void)
875 {
876 if (!cfg->options->entry_exit_movement)
877 return;
878
879 x_rot_mv.change_a_bit();
880 Arrangement::entry_exit_move();
881 }
882
883
884
885
886 // ==============================================================
887 // ViewMasterArrangement
888 // ==============================================================
889
ViewMasterArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)890 ViewMasterArrangement::ViewMasterArrangement(VDesktops &vdesks,
891 float fw, float fh,
892 FaceSet *fs,
893 Config *c,
894 Camera *cam)
895 : Arrangement (fs, c)
896 {
897 z_offset_distance = 10.0;
898
899 face_width = fw;
900 face_height = fh;
901
902 camera = cam;
903
904 calculate_faces(vdesks);
905
906 goto_face_mv.disable();
907 }
908
calculate_faces(VDesktops & vdesks)909 void ViewMasterArrangement::calculate_faces(VDesktops & vdesks)
910 {
911 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
912 &n_columns, &n_rows);
913
914 // current_face becomes the unrolled current face
915 current_face = current_col + (current_row * n_columns);
916
917 // n_faces becomes the total number of desktops
918 n_faces = n_columns * n_rows;
919
920
921 between_angle = 360 / n_faces;
922 per_face_change = between_angle;
923
924 center_distance = n_faces; // distance from the center
925
926 if (n_faces <= 3)
927 center_distance = 3.5;
928
929 float my_angle = ((FOV / 2.0) * PI) / 180.0;
930
931 z_offset_close = z_offset = -(float)((face_height/2.0) / tan(my_angle) +
932 get_base_z_offset());
933
934 Point tl,tr,bl,br;
935 int i;
936 float angle;
937 float center_x, center_y;
938 float x1, y1, x2, y2, x3, y3, x4, y4;
939
940 float r = sqrt ((face_height*face_height) +
941 (face_width*face_width)) / 2.0;
942
943 float angle_l, angle_s, hangle_l;
944
945 for (i = 0; i < n_faces; i++) {
946 angle = between_angle * i;
947
948 center_x = polar_to_x (center_distance, angle);
949 center_y = polar_to_y (center_distance, angle);
950
951 hangle_l = rad_to_deg(atan(face_width/face_height));
952 angle_l = hangle_l*2.0;
953 angle_s = 180 - angle_l;
954
955
956 x1 = polar_to_x(r, 90+angle+hangle_l) + center_x;
957 y1 = polar_to_y(r, 90+angle+hangle_l) + center_y;
958 x2 = polar_to_x(r, 90+angle-hangle_l) + center_x;
959 y2 = polar_to_y(r, 90+angle-hangle_l) + center_y;
960 x3 = polar_to_x(r, 90+angle+hangle_l+angle_s) + center_x;
961 y3 = polar_to_y(r, 90+angle+hangle_l+angle_s) + center_y;
962 x4 = polar_to_x(r, 90+angle+hangle_l+angle_s+angle_l) + center_x;
963 y4 = polar_to_y(r, 90+angle+hangle_l+angle_s+angle_l) + center_y;
964
965 tl.set(x1, y1, 0);
966 tr.set(x2, y2, 0);
967 bl.set(x3, y3, 0);
968 br.set(x4, y4, 0);
969
970 #if 0
971 if (i == 0) {
972 msgout(DEBUG, "hangle_l=%f\n", hangle_l);
973 msgout(DEBUG, "cx=%f cy=%f\n", center_x, center_y);
974 msgout(DEBUG, "r=%f\n", r);
975 msgout(DEBUG, "x=%f y=%f\n", x1, y1);
976 msgout(DEBUG, "x=%f y=%f\n", x2, y2);
977 msgout(DEBUG, "x=%f y=%f\n", x3, y3);
978 msgout(DEBUG, "x=%f y=%f\n", x4, y4);
979 }
980 #endif
981
982 face_set->set_face (i, tl, tr, bl, br);
983
984 }
985
986 goto_face_val = -current_face * between_angle;
987
988 make_display_list();
989 }
990
991
get_type()992 int ViewMasterArrangement::get_type ()
993 {
994 return FACE_TYPE_VIEWMASTER;
995 }
996
997
998 // this has to by overridden because of the 'current_face' variable
999 // which is private to this class
goto_random_face(void)1000 void ViewMasterArrangement::goto_random_face(void)
1001 {
1002 int which_one;
1003
1004 do {
1005 which_one = get_randomi (0, (n_columns * n_rows) - 1);
1006 } while (which_one == (current_col + (current_row * n_rows)));
1007
1008 current_face = which_one;
1009
1010 goto_face (which_one);
1011 }
1012
goto_right(void)1013 void ViewMasterArrangement::goto_right(void)
1014 {
1015 current_face++;
1016 if (current_face == n_faces)
1017 current_face = 0; // cycle around
1018
1019 // we are "unrolling" rows and columns so map the linear
1020 // "current_face" back to rows and columns
1021 current_col = current_face % n_columns;
1022 current_row = current_face / n_columns;
1023
1024 if (goto_face_mv.at_destination()) {
1025 goto_face_mv.init (&goto_face_val,
1026 goto_face_val, goto_face_val - per_face_change,
1027 cfg->options->face_change_steps, move_type);
1028 } else {
1029 goto_face_mv.init (&goto_face_val,
1030 goto_face_val, goto_face_mv.destination() - per_face_change,
1031 cfg->options->face_change_steps, move_type);
1032 }
1033 }
1034
goto_left(void)1035 void ViewMasterArrangement::goto_left(void)
1036 {
1037 if (current_face == 0)
1038 current_face = n_faces - 1; // cycle around
1039 else
1040 current_face--;
1041
1042 // we are "unrolling" rows and columns so map the linear
1043 // "current_face" back to rows and columns
1044 current_col = current_face % n_columns;
1045 current_row = current_face / n_columns;
1046
1047 if (goto_face_mv.at_destination()) {
1048 goto_face_mv.init (&goto_face_val,
1049 goto_face_val, goto_face_val + per_face_change,
1050 cfg->options->face_change_steps, move_type);
1051 } else {
1052 goto_face_mv.init (&goto_face_val,
1053 goto_face_val, goto_face_mv.destination() + per_face_change,
1054 cfg->options->face_change_steps, move_type);
1055 }
1056 }
1057
1058
1059
set_current_face(int c,int r)1060 void ViewMasterArrangement::set_current_face (int c, int r)
1061 {
1062 current_col = c;
1063 current_row = r;
1064 current_face = c + (r * n_columns);
1065 goto_face_val = -current_face * between_angle;
1066 goto_face_mv.disable();
1067 }
1068
get_distant_z_offset(void)1069 float ViewMasterArrangement::get_distant_z_offset(void)
1070 {
1071 return -(z_offset_distance);
1072 }
1073
1074
get_base_z_offset(void)1075 float ViewMasterArrangement::get_base_z_offset(void)
1076 {
1077 return 0.0;
1078 }
1079
1080
position_faces(void)1081 void ViewMasterArrangement::position_faces(void)
1082 {
1083 //glTranslatef(0.0f,0.0f, z_offset);
1084 camera->position.z = -z_offset;
1085
1086 //glTranslatef(-center_distance, 0.0f, 0.0f);
1087 camera->position.x = center_distance;
1088 camera->viewvector.x = center_distance;
1089
1090 camera->Look();
1091
1092 glRotatef(goto_face_val, 0.0f, 0.0f, 1.0f);
1093 }
1094
render()1095 void ViewMasterArrangement::render()
1096 {
1097 //glCallList(face_list);
1098 face_set->render_all();
1099 }
1100
do_movement(void)1101 void ViewMasterArrangement::do_movement(void)
1102 {
1103 if (!goto_face_mv.at_destination())
1104 goto_face_mv.change_a_bit();
1105 else
1106 clamp_degrees (&goto_face_val);
1107 }
1108
1109
1110 // ==============================================================
1111 // PriceIsRightArrangement
1112 // ==============================================================
PriceIsRightArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)1113 PriceIsRightArrangement::PriceIsRightArrangement(VDesktops &vdesks,
1114 float fw, float fh,
1115 FaceSet *fs,
1116 Config *c,
1117 Camera *cam)
1118 : Arrangement (fs, c)
1119 {
1120 face_width = fw;
1121 face_height = fh;
1122
1123 camera = cam;
1124
1125 calculate_faces(vdesks);
1126
1127 goto_face_mv.disable();
1128
1129 }
1130
calculate_faces(VDesktops & vdesks)1131 void PriceIsRightArrangement::calculate_faces(VDesktops & vdesks)
1132 {
1133 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
1134 &n_columns, &n_rows);
1135
1136 // current_face becomes the unrolled current face
1137 current_face = current_col + (current_row * n_columns);
1138
1139 // n_faces becomes the total number of desktops
1140 n_faces = n_columns * n_rows;
1141
1142 side_angle = 360.0 / (float)n_faces;
1143 per_face_change = -side_angle;
1144
1145 goto_face_val = 360 + (side_angle * current_face);
1146
1147
1148 float circum = face_height * 1.8 * n_faces;
1149 radius = circum / (2.0 * PI);
1150
1151
1152
1153 float my_angle = ((FOV / 2.0) * PI) / 180.0;
1154
1155 z_offset_close = z_offset = -(float)((face_height/2.0) / tan(my_angle) +
1156 get_base_z_offset());
1157
1158
1159 int i;
1160 float half_face_height = face_height / 2.0;
1161 float half_face_width = face_width / 2.0;
1162
1163 Point tl,tr,bl,br;
1164
1165 for (i = 0; i < n_faces; i++) {
1166
1167 tl.set (-half_face_width, half_face_height, 0);
1168 tr.set ( half_face_width, half_face_height, 0);
1169 bl.set (-half_face_width, -half_face_height, 0);
1170 br.set ( half_face_width, -half_face_height, 0);
1171
1172 translate (tl.v, 0, 0, radius);
1173 rotate_x (tl.v, -side_angle * i);
1174
1175 translate (tr.v, 0, 0, radius);
1176 rotate_x (tr.v, -side_angle * i);
1177
1178 translate (bl.v, 0, 0, radius);
1179 rotate_x (bl.v, -side_angle * i);
1180
1181 translate (br.v, 0, 0, radius);
1182 rotate_x (br.v, -side_angle * i);
1183
1184 //msgout(DEBUG, "[%i] = %f, %f, %f\n", i, tl.v[0], tl.v[1], tl.v[2]);
1185
1186 face_set->set_face (i, tl, tr, bl, br);
1187 }
1188
1189 //make_display_list();
1190
1191 }
1192
1193
get_type()1194 int PriceIsRightArrangement::get_type ()
1195 {
1196 return FACE_TYPE_PRICEISRIGHT;
1197 }
1198
1199 // this has to by overridden because of the 'current_face' variable
1200 // which is private to this class
goto_random_face(void)1201 void PriceIsRightArrangement::goto_random_face(void)
1202 {
1203 int which_one;
1204
1205 do {
1206 which_one = get_randomi (0, (n_columns * n_rows) - 1);
1207 } while (which_one == (current_col + (current_row * n_rows)));
1208
1209 current_face = which_one;
1210
1211 goto_face (which_one);
1212 }
1213
1214
goto_right(void)1215 void PriceIsRightArrangement::goto_right(void)
1216 {
1217 current_face++;
1218 if (current_face == n_faces)
1219 current_face = 0; // cycle around
1220
1221 // we are "unrolling" rows and columns so map the linear
1222 // "current_face" back to rows and columns
1223 current_col = current_face % n_columns;
1224 current_row = current_face / n_columns;
1225
1226 if (goto_face_mv.at_destination()) {
1227 goto_face_mv.init (&goto_face_val,
1228 goto_face_val, goto_face_val - per_face_change,
1229 cfg->options->face_change_steps, move_type);
1230 } else {
1231 goto_face_mv.init (&goto_face_val,
1232 goto_face_val, goto_face_mv.destination() - per_face_change,
1233 cfg->options->face_change_steps, move_type);
1234 }
1235 }
1236
goto_left(void)1237 void PriceIsRightArrangement::goto_left(void)
1238 {
1239 if (current_face == 0)
1240 current_face = n_faces - 1; // cycle around
1241 else
1242 current_face--;
1243
1244 // we are "unrolling" rows and columns so map the linear
1245 // "current_face" back to rows and columns
1246 current_col = current_face % n_columns;
1247 current_row = current_face / n_columns;
1248
1249 if (goto_face_mv.at_destination()) {
1250 goto_face_mv.init (&goto_face_val,
1251 goto_face_val, goto_face_val + per_face_change,
1252 cfg->options->face_change_steps, move_type);
1253 } else {
1254 goto_face_mv.init (&goto_face_val,
1255 goto_face_val, goto_face_mv.destination() + per_face_change,
1256 cfg->options->face_change_steps, move_type);
1257 }
1258 }
1259
1260
set_current_face(int c,int r)1261 void PriceIsRightArrangement::set_current_face (int c, int r)
1262 {
1263 current_col = c;
1264 current_row = r;
1265 current_face = c + (r * n_columns);
1266 goto_face_val = 360 + (side_angle * current_face);
1267 goto_face_mv.disable();
1268 }
1269
get_distant_z_offset(void)1270 float PriceIsRightArrangement::get_distant_z_offset(void)
1271 {
1272 return -(z_offset_distance + get_base_z_offset());
1273 }
1274
get_base_z_offset(void)1275 float PriceIsRightArrangement::get_base_z_offset(void)
1276 {
1277 return (radius ); //(face_width/2.0) / tan (deg_to_rad(side_angle/2.0)));
1278 }
1279
1280
do_movement(void)1281 void PriceIsRightArrangement::do_movement(void)
1282 {
1283 if (!goto_face_mv.at_destination())
1284 goto_face_mv.change_a_bit ();
1285 else
1286 clamp_degrees(&goto_face_val);
1287 }
1288
position_faces(void)1289 void PriceIsRightArrangement::position_faces(void)
1290 {
1291 //glTranslatef(0.0f,0.0f, z_offset);
1292 camera->position.z = -z_offset;
1293
1294 camera->Look();
1295
1296 glRotatef(goto_face_val, 1.0f, 0.0f, 0.0f);
1297 }
1298
1299
1300
1301 // ==============================================================
1302 // LinearArrangement
1303 // ==============================================================
1304
LinearArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)1305 LinearArrangement::LinearArrangement(VDesktops &vdesks,
1306 float fw, float fh,
1307 FaceSet *fs,
1308 Config *c,
1309 Camera *cam)
1310 : Arrangement (fs, c)
1311 {
1312 z_offset_distance = 10.0;
1313
1314 spin_z_rot = 0;
1315
1316 //cfg->options->zoom_steps = 60;
1317
1318 face_width = fw;
1319 face_height = fh;
1320
1321 camera = cam;
1322
1323 calculate_faces(vdesks);
1324
1325 x_trans_mv.disable();
1326 y_trans_mv.disable();
1327 spin_mv.disable();
1328 }
1329
calculate_faces(VDesktops & vdesks)1330 void LinearArrangement::calculate_faces(VDesktops & vdesks)
1331 {
1332
1333 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
1334 &n_columns, &n_rows);
1335
1336 between = cfg->options->linear_spacing;
1337
1338 float my_angle = ((FOV / 2.0) * PI) / 180.0;
1339
1340 z_offset_close = z_offset = -(float)((face_height/2.0) / tan(my_angle) +
1341 get_base_z_offset());
1342
1343 //msgout(DEBUG, "z_offset_close = %lf\n", z_offset_close);
1344
1345
1346 Point tl,tr,bl,br;
1347 int i, j, count = 0;
1348 float x, y;
1349 float half_face_height = face_height / 2.0;
1350 float half_face_width = face_width / 2.0;
1351
1352 X_Trans = -(half_face_width + (current_col * (face_width + between)));
1353 Y_Trans = ((current_row * (face_height + between)) + half_face_height);
1354
1355 //msgout (DEBUG, "constructor: Y_Trans = %f\n", Y_Trans);
1356
1357 for (i = 0; i < n_rows; i++) {
1358 for (j = 0; j < n_columns; j++) {
1359
1360 y = i * (face_height + between);
1361 x = j * (face_width + between);
1362
1363 tl.set(x, -y, 0);
1364 tr.set(x + face_width, -y, 0);
1365 bl.set(x, -y - face_height, 0);
1366 br.set(x + face_width, -y - face_height, 0);
1367
1368 face_set->set_face (count, tl, tr, bl, br);
1369
1370 count ++;
1371 }
1372 }
1373
1374 make_display_list();
1375
1376 }
1377
get_type()1378 int LinearArrangement::get_type ()
1379 {
1380 return FACE_TYPE_LINEAR;
1381 }
1382
1383
set_current_face(int c,int r)1384 void LinearArrangement::set_current_face (int c, int r)
1385 {
1386 float half_face_width = face_width / 2.0;
1387 float half_face_height = face_height / 2.0;
1388
1389 current_row = r;
1390 current_col = c;
1391 current_face = c + (r * n_columns);
1392
1393 X_Trans = -(half_face_width + (current_col * (face_width + between)));
1394 Y_Trans = ((current_row * (face_height + between)) + half_face_height);
1395
1396 msgout (DEBUG, "set_current_face: Y_Trans = %f, "
1397 "current_col=%d, current_row=%d, face_height=%f, "
1398 "between=%f, hfh=%f\n", Y_Trans, current_col, current_row,
1399 face_height, between, half_face_height);
1400
1401 x_trans_mv.disable();
1402 y_trans_mv.disable();
1403 }
1404
get_distant_z_offset(void)1405 float LinearArrangement::get_distant_z_offset(void)
1406 {
1407 return -(z_offset_distance);
1408 }
1409
1410
get_base_z_offset(void)1411 float LinearArrangement::get_base_z_offset(void)
1412 {
1413 return 0.0;
1414 }
1415
in_goto(void)1416 int LinearArrangement::in_goto (void)
1417 {
1418 return !x_trans_mv.at_destination() || !y_trans_mv.at_destination();
1419 }
1420
goto_left(void)1421 void LinearArrangement::goto_left(void)
1422 {
1423 if (current_col != 0)
1424 current_col--;
1425 else
1426 return;
1427
1428 if (x_trans_mv.at_destination()) {
1429 //if ((X_Trans + (face_width+between)) > MIN_X_Trans) // because its negative
1430 // break;
1431 x_trans_mv.init (&X_Trans, X_Trans, X_Trans + (face_width+between),
1432 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1433 } else {
1434 //if ((x_trans_mv.destination() + (face_width+between)) > MIN_X_Trans) // because its negative
1435 // break;
1436 x_trans_mv.init (&X_Trans, X_Trans, x_trans_mv.destination() + (face_width+between),
1437 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1438 }
1439 }
1440
goto_right(void)1441 void LinearArrangement::goto_right(void)
1442 {
1443 if (current_col != (n_columns - 1))
1444 current_col++;
1445 else
1446 return;
1447
1448 if (x_trans_mv.at_destination()) {
1449 x_trans_mv.init (&X_Trans, X_Trans, X_Trans - (face_width + between),
1450 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1451 } else {
1452 x_trans_mv.init (&X_Trans, X_Trans,
1453 x_trans_mv.destination() - (face_width+between),
1454 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1455 }
1456 }
1457
goto_up(void)1458 void LinearArrangement::goto_up(void)
1459 {
1460 if (current_row != 0)
1461 current_row--;
1462 else
1463 return;
1464
1465 if (y_trans_mv.at_destination()) {
1466 y_trans_mv.init (&Y_Trans, Y_Trans, Y_Trans - (face_height+between),
1467 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1468 } else {
1469 y_trans_mv.init (&Y_Trans, Y_Trans, y_trans_mv.destination() - (face_height+between),
1470 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1471 }
1472 }
1473
goto_down(void)1474 void LinearArrangement::goto_down(void)
1475 {
1476 if (current_row != (n_rows - 1))
1477 current_row++;
1478 else
1479 return;
1480
1481 if (y_trans_mv.at_destination()) {
1482 y_trans_mv.init (&Y_Trans, Y_Trans, Y_Trans + (face_height + between),
1483 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1484 } else {
1485 y_trans_mv.init (&Y_Trans, Y_Trans,
1486 y_trans_mv.destination() + (face_height + between),
1487 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1488 }
1489 }
1490
goto_face(desktop_coords_t dest)1491 float LinearArrangement::goto_face (desktop_coords_t dest)
1492 {
1493 signed int nummove;
1494
1495 if (//dest.column == current_col ||
1496 dest.column < 0
1497 || dest.column >= n_columns)
1498 return 0;
1499
1500 nummove = dest.column - current_col;
1501 current_col = dest.column;
1502
1503 if (x_trans_mv.at_destination()) {
1504 x_trans_mv.init (&X_Trans, X_Trans,
1505 X_Trans - ((float)nummove * (face_width + between)),
1506 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1507 } else {
1508 x_trans_mv.init (&X_Trans, X_Trans,
1509 x_trans_mv.destination() - ((float)nummove * (face_width + between)),
1510 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1511 }
1512
1513
1514 if (//dest.row == current_row ||
1515 dest.row < 0
1516 || dest.row >= n_rows)
1517 return 0;
1518
1519 nummove = dest.row - current_row;
1520 current_row = dest.row;
1521
1522 if (y_trans_mv.at_destination()) {
1523 y_trans_mv.init (&Y_Trans, Y_Trans,
1524 Y_Trans + ((float)nummove * (face_height + between)),
1525 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1526 } else {
1527 y_trans_mv.init (&Y_Trans, Y_Trans,
1528 y_trans_mv.destination() + ((float)nummove * (face_height + between)),
1529 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1530 }
1531 return cfg->options->face_change_steps;
1532
1533
1534 }
1535
1536
1537 #if 0
1538 float LinearArrangement::goto_column(int column)
1539 {
1540 signed int nummove;
1541
1542 if (column == current_col
1543 || column < 0
1544 || column >= n_columns)
1545 return 0;
1546
1547 nummove = column - current_col;
1548 current_col = column;
1549
1550 if (x_trans_mv.at_destination()) {
1551 x_trans_mv.init (&X_Trans, X_Trans,
1552 X_Trans - ((float)nummove * (face_width + between)),
1553 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1554 } else {
1555 x_trans_mv.init (&X_Trans, X_Trans,
1556 x_trans_mv.destination() - ((float)nummove * (face_width + between)),
1557 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1558 }
1559 return cfg->options->face_change_steps;
1560 }
1561
1562
1563 float LinearArrangement::goto_row(int row)
1564 {
1565 signed int nummove;
1566
1567 if (row == current_row
1568 || row < 0
1569 || row >= n_rows)
1570 return 0;
1571
1572 nummove = row - current_row;
1573 current_row = row;
1574
1575 if (y_trans_mv.at_destination()) {
1576 y_trans_mv.init (&Y_Trans, Y_Trans,
1577 Y_Trans - ((float)nummove * (face_width + between)),
1578 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1579 } else {
1580 y_trans_mv.init (&Y_Trans, Y_Trans,
1581 y_trans_mv.destination() - ((float)nummove * (face_width + between)),
1582 cfg->options->face_change_steps, LINEAR_MOVE_TYPE);
1583 }
1584 return cfg->options->face_change_steps;
1585 }
1586 #endif // if 0
1587
1588
position_faces(void)1589 void LinearArrangement::position_faces(void)
1590 {
1591 //if (spin_z_rot)
1592 // glRotatef(spin_z_rot,0.0f,0.0f,1.0f);
1593
1594 //glTranslatef(0.0f,0.0f, z_offset);
1595 camera->position.z = -z_offset;
1596
1597 //glTranslatef(X_Trans, 0.0f, 0.0f);
1598 camera->position.x = -X_Trans;
1599 camera->viewvector.x = -X_Trans;
1600
1601 //glTranslatef(0.0f, Y_Trans, 0.0f);
1602 camera->position.y = -Y_Trans;
1603 camera->viewvector.y = -Y_Trans;
1604
1605 camera->Look();
1606 }
1607
position_lighting(void)1608 void LinearArrangement::position_lighting(void)
1609 {
1610 // don't do anything as this will keep the light center on our
1611 // current view
1612 }
1613
render()1614 void LinearArrangement::render()
1615 {
1616 //glCallList(face_list);
1617 face_set->render_all();
1618 }
1619
1620
do_movement(void)1621 void LinearArrangement::do_movement(void)
1622 {
1623 if (!x_trans_mv.at_destination()) {
1624 x_trans_mv.change_a_bit();
1625 }
1626 if (!y_trans_mv.at_destination()) {
1627 y_trans_mv.change_a_bit();
1628 }
1629 }
1630
entry_exit_move(void)1631 void LinearArrangement::entry_exit_move(void)
1632 {
1633 //spin_mv.change_a_bit();
1634 Arrangement::entry_exit_move();
1635 }
1636
exit_movement_start(void)1637 void LinearArrangement::exit_movement_start(void)
1638 {
1639 //spin_mv.init (&spin_z_rot,
1640 // 0.0, 360.0,
1641 // cfg->options->zoom_steps,
1642 // Movement::MOVE_TYPE_WACK);
1643 Arrangement::exit_movement_start();
1644 }
1645
exit_movement_cancel(void)1646 void LinearArrangement::exit_movement_cancel(void)
1647 {
1648 //spin_mv.init (&spin_z_rot,
1649 // spin_z_rot, 0.0,
1650 // cfg->options->zoom_steps,
1651 // Movement::MOVE_TYPE_WACK);
1652 Arrangement::exit_movement_cancel();
1653 }
1654
1655
1656
1657 // ==============================================================
1658 // FlipArrangement
1659 // ==============================================================
1660
1661 // override so as to prevent "spin" from getting short circuited
in_goto(void)1662 int FlipArrangement::in_goto (void)
1663 {
1664 return !goto_face_mv.at_destination() || !spin_mv.at_destination();
1665 }
1666
cant_exit_in_goto(void)1667 int FlipArrangement::cant_exit_in_goto(void)
1668 {
1669 return 1; // this is always true
1670 }
1671
1672 // Faces in FaceSet aren't rendered at all, we render our own
render()1673 void FlipArrangement::render()
1674 {
1675 face_A->render();
1676 face_B->render();
1677 }
1678
1679 // display list not utilized for this one
make_display_list(void)1680 void FlipArrangement::make_display_list(void)
1681 { }
1682
1683
FlipArrangement(VDesktops & vdesks,float fw,float fh,FaceSet * fs,Config * c,Camera * cam)1684 FlipArrangement::FlipArrangement(VDesktops & vdesks,
1685 float fw, float fh,
1686 FaceSet *fs,
1687 Config *c,
1688 Camera *cam)
1689 : Arrangement (fs, c)
1690 {
1691 face_width = fw;
1692 face_height = fh;
1693
1694 camera = cam;
1695
1696 face_A = new Face (0);
1697 if (!face_A) {
1698 msgout(ERROR, "out of memory\n");
1699 exit (-1);
1700 }
1701
1702 face_B = new Face (0);
1703 if (!face_B) {
1704 msgout(ERROR, "out of memory\n");
1705 exit (-1);
1706 }
1707
1708 showing_face = NULL;
1709
1710 calculate_faces(vdesks);
1711
1712 goto_face_val = 0;
1713
1714 goto_face_mv.disable();
1715
1716 spin_mv.disable();
1717 spin_val = 0;
1718 }
1719
~FlipArrangement()1720 FlipArrangement::~FlipArrangement ()
1721 {
1722 delete face_A;
1723 delete face_B;
1724 }
1725
get_type()1726 int FlipArrangement::get_type()
1727 {
1728 return FACE_TYPE_FLIP;
1729 }
1730
calculate_faces(VDesktops & vdesks)1731 void FlipArrangement::calculate_faces(VDesktops & vdesks)
1732 {
1733 vdesks.get_vdesktop_info (¤t_col, ¤t_row,
1734 &n_columns, &n_rows);
1735
1736 //msgout (DEBUG, "at %d x %d (%d, %d)\n", current_row, current_col, n_rows, n_columns);
1737
1738 // current_face becomes the unrolled current face
1739 current_face = current_col + (current_row * n_columns);
1740
1741 // n_faces becomes the total number of desktops
1742 n_faces = n_columns * n_rows;
1743
1744 z_offset_distance = 10.0;
1745
1746 per_face_change = 180;
1747
1748
1749 float my_angle = ((FOV / 2.0) * PI) / 180.0;
1750
1751 z_offset_close = z_offset = -(float)((face_height/2.0) / tan(my_angle) +
1752 get_base_z_offset());
1753
1754 Point tl, tr, bl, br;
1755
1756 float half_face_height = face_height / 2.0;
1757 float half_face_width = face_width / 2.0;
1758
1759 tl.set (-half_face_width, half_face_height, .1);
1760 tr.set ( half_face_width, half_face_height, .1);
1761 bl.set (-half_face_width, -half_face_height, .1);
1762 br.set ( half_face_width, -half_face_height, .1);
1763
1764 face_A->set_corners(tl, tr, bl, br);
1765
1766 tl.set ( half_face_width, half_face_height, -.1);
1767 tr.set (-half_face_width, half_face_height, -.1);
1768 bl.set ( half_face_width, -half_face_height, -.1);
1769 br.set (-half_face_width, -half_face_height, -.1);
1770
1771 face_B->set_corners(tl, tr, bl, br);
1772
1773 if (!showing_face)
1774 showing_face = face_A;
1775
1776 //msgout (DEBUG, "set tid = %d\n", face_set->get_texture_id(current_face));
1777
1778 showing_face->set_texture_id(face_set->get_texture_id(current_face));
1779 }
1780
1781 // there is no entry exit for flips
entry_movement_start(void)1782 void FlipArrangement::entry_movement_start(void)
1783 {
1784 //msgout (DEBUG, "----------4 set tid = %d\n", face_set->get_texture_id(current_face));
1785 showing_face->set_texture_id(face_set->get_texture_id(current_face));
1786 }
1787
exit_movement_start(void)1788 void FlipArrangement::exit_movement_start(void)
1789 {}
exit_movement_cancel(void)1790 void FlipArrangement::exit_movement_cancel(void)
1791 {}
entry_exit_move(void)1792 void FlipArrangement::entry_exit_move(void)
1793 {}
1794
is_entry_movement_done(void)1795 int FlipArrangement::is_entry_movement_done(void)
1796 { return 1; }
1797
is_exit_movement_done(void)1798 int FlipArrangement::is_exit_movement_done(void)
1799 { return 1; }
1800
1801
set_current_face(int c,int r)1802 void FlipArrangement::set_current_face (int c, int r)
1803 {
1804 current_face = c + (r * n_columns);
1805 current_col = c;
1806 current_row = r;
1807
1808 //msgout (DEBUG, "---------- set tid = %d\n", face_set->get_texture_id(current_face));
1809 showing_face->set_texture_id(face_set->get_texture_id(current_face));
1810
1811 goto_face_val = goto_face_mv.destination();
1812 goto_face_mv.disable();
1813 }
1814
get_distant_z_offset(void)1815 float FlipArrangement::get_distant_z_offset(void)
1816 {
1817 return -(z_offset_distance);
1818 }
1819
1820
get_base_z_offset(void)1821 float FlipArrangement::get_base_z_offset(void)
1822 {
1823 return 0.1;
1824 }
1825
1826
position_faces(void)1827 void FlipArrangement::position_faces(void)
1828 {
1829 //glTranslatef(0.0f,0.0f, z_offset);
1830 camera->position.z = -z_offset;
1831
1832 camera->Look();
1833
1834 glRotatef(goto_face_val, 0.0f, 1.0f, 0.0f);
1835 if (spin_val) {
1836 glRotatef(spin_val, 1.0f, 1.0f, 1.0f);
1837 }
1838 }
1839
do_movement(void)1840 void FlipArrangement::do_movement(void)
1841 {
1842 if (!goto_face_mv.at_destination())
1843 goto_face_mv.change_a_bit();
1844 else
1845 clamp_degrees (&goto_face_val);
1846
1847 if (!spin_mv.at_destination())
1848 spin_mv.change_a_bit();
1849 else
1850 clamp_degrees (&spin_val);
1851 }
1852
1853
goto_face(desktop_coords_t dest)1854 float FlipArrangement::goto_face (desktop_coords_t dest)
1855 {
1856 if ((dest.column == current_col && dest.row == current_row)
1857 || dest.column < 0
1858 || dest.column >= n_columns
1859 || dest.row < 0
1860 || dest.row >= n_rows)
1861 {
1862 return 0;
1863 }
1864
1865 int newface = dest.column + (dest.row * n_columns);
1866
1867 int current = current_col + (current_row * n_columns);
1868
1869 int number = n_columns * n_rows;
1870
1871 int direction = 1;
1872
1873 // figure out which way to turn to get to the face.
1874 // This code was taken from carousel goto_face and can
1875 // be improved/simplified no doubt. This still does not
1876 // work if we are mid-goto.
1877 if (newface > current) {
1878 if ( (newface - current) <
1879 ((current + number) - newface) )
1880 {
1881 // left
1882 direction = -1;
1883 } else {
1884 // right
1885 direction = 1;
1886 }
1887 } else {
1888 // newface < current
1889
1890 if ( (current - newface) >
1891 ((newface + number) - current) )
1892 {
1893 // left
1894 direction = -1;
1895 } else {
1896 // right
1897 direction = 1;
1898 }
1899 }
1900
1901 if (goto_face_mv.at_destination())
1902 goto_face_mv.init (&goto_face_val, goto_face_val,
1903 goto_face_val + per_face_change * direction,
1904 cfg->options->face_change_steps, move_type);
1905 else
1906 goto_face_mv.init (&goto_face_val, goto_face_val,
1907 goto_face_mv.destination() + per_face_change,
1908 cfg->options->face_change_steps, move_type);
1909
1910 current_face = newface;
1911 current_col = dest.column;
1912 current_row = dest.row;
1913
1914 // swap faces
1915 if (showing_face == face_A) {
1916 showing_face = face_B;
1917 } else {
1918 showing_face = face_A;
1919 }
1920
1921 //msgout (DEBUG, "---------1 set tid = %d\n", face_set->get_texture_id(current_face));
1922 showing_face->set_texture_id(face_set->get_texture_id(current_face));
1923
1924 return cfg->options->face_change_steps;
1925 }
1926
1927
goto_up(void)1928 void FlipArrangement::goto_up(void)
1929 {
1930 if (spin_mv.at_destination())
1931 spin_mv.init(&spin_val, 0.0, 360.0, 2*cfg->options->face_change_steps, move_type);
1932 else
1933 spin_mv.init(&spin_val, spin_val, spin_mv.destination() + 360.0,
1934 2*cfg->options->face_change_steps, move_type);
1935 }
1936
goto_down(void)1937 void FlipArrangement::goto_down(void)
1938 { }
1939
1940
1941 // this has to by overridden because of the 'current_face' variable
1942 // which is private to this class
goto_random_face(void)1943 void FlipArrangement::goto_random_face(void)
1944 {
1945 int which_one;
1946
1947 do {
1948 which_one = get_randomi (0, (n_columns * n_rows) - 1);
1949 } while (which_one == (current_col + (current_row * n_rows)));
1950
1951 current_face = which_one;
1952
1953 Arrangement::goto_face (which_one);
1954 }
1955
goto_right(void)1956 void FlipArrangement::goto_right(void)
1957 {
1958 current_face++;
1959 if (current_face == n_faces)
1960 current_face = 0; // cycle around
1961
1962 // we are "unrolling" rows and columns so map the linear
1963 // "current_face" back to rows and columns
1964 current_col = current_face % n_columns;
1965 current_row = current_face / n_columns;
1966
1967 if (goto_face_mv.at_destination()) {
1968 goto_face_mv.init (&goto_face_val,
1969 goto_face_val, goto_face_val - per_face_change,
1970 cfg->options->face_change_steps, move_type);
1971 } else {
1972 goto_face_mv.init (&goto_face_val,
1973 goto_face_val, goto_face_mv.destination() - per_face_change,
1974 cfg->options->face_change_steps, move_type);
1975 }
1976
1977 // swap faces
1978 if (showing_face == face_A) {
1979 showing_face = face_B;
1980 } else {
1981 showing_face = face_A;
1982 }
1983
1984 //msgout (DEBUG, "----------2 set tid = %d\n", face_set->get_texture_id(current_face));
1985 showing_face->set_texture_id(face_set->get_texture_id(current_face));
1986 }
1987
goto_left(void)1988 void FlipArrangement::goto_left(void)
1989 {
1990 if (current_face == 0)
1991 current_face = n_faces - 1; // cycle around
1992 else
1993 current_face--;
1994
1995 // we are "unrolling" rows and columns so map the linear
1996 // "current_face" back to rows and columns
1997 current_col = current_face % n_columns;
1998 current_row = current_face / n_columns;
1999
2000 if (goto_face_mv.at_destination()) {
2001 goto_face_mv.init (&goto_face_val,
2002 goto_face_val, goto_face_val + per_face_change,
2003 cfg->options->face_change_steps, move_type);
2004 } else {
2005 goto_face_mv.init (&goto_face_val,
2006 goto_face_val, goto_face_mv.destination() + per_face_change,
2007 cfg->options->face_change_steps, move_type);
2008 }
2009
2010 // swap faces
2011 if (showing_face == face_A) {
2012 showing_face = face_B;
2013 } else {
2014 showing_face = face_A;
2015 }
2016
2017 //msgout (DEBUG, "----------3 set tid = %d\n", face_set->get_texture_id(current_face));
2018 showing_face->set_texture_id(face_set->get_texture_id(current_face));
2019 }
2020
2021
allow_blending(void)2022 int FlipArrangement::allow_blending(void)
2023 {
2024 return 0; // flip looks bad with blending
2025 }
2026
2027 #endif // if !defined ONE_ARRANGEMENT_ONLY
2028