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 (&current_col, &current_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 (&current_col, &current_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 (&current_col, &current_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 (&current_col, &current_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 (&current_col, &current_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 (&current_col, &current_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