transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / libs / splines / splines.h
1 #ifndef __SPLINES_H\r
2 #define __SPLINES_H\r
3 \r
4 #define GTKRADIANT\r
5 \r
6 #ifndef CAMERA_PLUGIN\r
7 #ifdef GTKRADIANT\r
8 #include "misc_def.h"\r
9 #include "igl_to_qgl.h"\r
10 #endif\r
11 #endif\r
12 \r
13 #include "util_list.h"\r
14 #include "util_str.h"\r
15 #include "math_vector.h"\r
16 \r
17 typedef int fileHandle_t;\r
18 \r
19 extern void glBox(idVec3 &color, idVec3 &point, float size);\r
20 extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);\r
21 \r
22 static idVec4 blue(0, 0, 1, 1);\r
23 static idVec4 red(1, 0, 0, 1);\r
24 \r
25 class idPointListInterface {\r
26 public:\r
27         idPointListInterface() {\r
28                 selectedPoints.Clear();\r
29         };\r
30         virtual ~idPointListInterface() {};\r
31         \r
32         virtual int numPoints() {\r
33                 return 0;\r
34         }\r
35         \r
36         virtual void addPoint(const float x, const float y, const float z) {}\r
37         virtual void addPoint(const idVec3 &v) {}\r
38         virtual void removePoint(int index) {}\r
39         virtual idVec3 *getPoint(int index) { return NULL; }\r
40         \r
41         int     selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {\r
42                 idVec3 origin(ox, oy, oz);\r
43                 idVec3 dir(dx, dy, dz);\r
44                 return selectPointByRay(origin, dir, single);\r
45         }\r
46 \r
47         int     selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {\r
48                 int             i, besti, count;\r
49                 float   d, bestd;\r
50                 idVec3  temp, temp2;\r
51 \r
52                 // find the point closest to the ray\r
53                 besti = -1;\r
54                 bestd = 8;\r
55                 count = numPoints();\r
56 \r
57                 for (i=0; i < count; i++) {\r
58                         temp = *getPoint(i);\r
59                         temp2 = temp;\r
60                         temp -= origin;\r
61                         d = DotProduct(temp, direction);\r
62                         __VectorMA (origin, d, direction, temp);\r
63                         temp2 -= temp;\r
64                         d = temp2.Length();\r
65                         if (d <= bestd) {\r
66                                 bestd = d;\r
67                                 besti = i;\r
68                         }\r
69                 }\r
70 \r
71                 if (besti >= 0) {\r
72                         selectPoint(besti, single);\r
73                 }\r
74 \r
75                 return besti;\r
76         }\r
77 \r
78         int isPointSelected(int index) {\r
79                 int count = selectedPoints.Num();\r
80                 for (int i = 0; i < count; i++) {\r
81                         if (selectedPoints[i] == index) {\r
82                                 return i;\r
83                         }\r
84                 }\r
85                 return -1;\r
86         }\r
87         \r
88         int selectPoint(int index, bool single) {\r
89                 if (index >= 0 && index < numPoints()) {\r
90                         if (single) {\r
91                                 deselectAll();\r
92                         } else {\r
93                                 if (isPointSelected(index) >= 0) {\r
94                                         selectedPoints.Remove(index);\r
95                                 }\r
96                         }\r
97                         return selectedPoints.Append(index);\r
98                 }\r
99                 return -1;\r
100         }\r
101         \r
102         void selectAll() {\r
103                 selectedPoints.Clear();\r
104                 for (int i = 0; i < numPoints(); i++) {\r
105                         selectedPoints.Append(i);\r
106                 }\r
107         }\r
108 \r
109         void deselectAll() {\r
110                 selectedPoints.Clear();\r
111         }\r
112 \r
113         int numSelectedPoints();\r
114     \r
115         idVec3 *getSelectedPoint(int index) {\r
116                 assert(index >= 0 && index < numSelectedPoints());\r
117                 return getPoint(selectedPoints[index]);\r
118         }\r
119         \r
120         virtual void updateSelection(float x, float y, float z) {\r
121                 idVec3 move(x, y, z);\r
122                 updateSelection(move);\r
123         }\r
124 \r
125         virtual void updateSelection(const idVec3 &move) {\r
126                 int count = selectedPoints.Num();\r
127                 for (int i = 0; i < count; i++) {\r
128                         *getPoint(selectedPoints[i]) += move;\r
129                 }\r
130         }\r
131 \r
132         void drawSelection() {\r
133                 int count = selectedPoints.Num();\r
134                 for (int i = 0; i < count; i++) {\r
135                         glBox(red, *getPoint(selectedPoints[i]), 4);\r
136                 }\r
137         }\r
138 \r
139 protected:\r
140         idList<int> selectedPoints;\r
141 \r
142 };\r
143 \r
144 \r
145 class idSplineList {\r
146 \r
147 public:\r
148 \r
149         idSplineList() {\r
150                 clear();\r
151         }\r
152 \r
153         idSplineList(const char *p) {\r
154                 clear();\r
155                 name = p;\r
156         };\r
157 \r
158         ~idSplineList() {\r
159                 clear();\r
160         };\r
161 \r
162         void clearControl() {\r
163                 for (int i = 0; i < controlPoints.Num(); i++) {\r
164                         delete controlPoints[i];\r
165                 }\r
166                 controlPoints.Clear();\r
167         }\r
168 \r
169         void clearSpline() {\r
170                 for (int i = 0; i < splinePoints.Num(); i++) {\r
171                         delete splinePoints[i];\r
172                 }\r
173                 splinePoints.Clear();\r
174         }\r
175 \r
176         void parse(const char *(*text));\r
177         void write(fileHandle_t file, const char *name);\r
178 \r
179         void clear() {\r
180                 clearControl();\r
181                 clearSpline();\r
182                 splineTime.Clear();\r
183                 selected = NULL;\r
184                 dirty = true;\r
185                 activeSegment = 0;\r
186                 granularity = 0.025f;\r
187                 pathColor.set(1.0f, 0.5f, 0.0f);\r
188                 controlColor.set(0.7f, 0.0f, 1.0f);\r
189                 segmentColor.set(0.0f, 0.0f, 1.0f);\r
190                 activeColor.set(1.0f, 0.0f, 0.0f);\r
191         }\r
192 \r
193         void initPosition(long startTime, long totalTime);\r
194         const idVec3 *getPosition(long time);\r
195 \r
196 \r
197         void draw(bool editMode);\r
198         void addToRenderer();\r
199 \r
200         void setSelectedPoint(idVec3 *p);\r
201         idVec3 *getSelectedPoint() {\r
202           return selected;\r
203         }\r
204 \r
205         void addPoint(const idVec3 &v) {\r
206                 controlPoints.Append(new idVec3(v));\r
207                 dirty = true;\r
208         }\r
209 \r
210         void addPoint(float x, float y, float z) {\r
211                 controlPoints.Append(new idVec3(x, y, z));\r
212                 dirty = true;\r
213         }\r
214 \r
215         void updateSelection(const idVec3 &move);\r
216 \r
217         void startEdit() {\r
218                 editMode = true;\r
219         }\r
220                 \r
221         void stopEdit() {\r
222                 editMode = false;\r
223         }\r
224 \r
225         void buildSpline();\r
226 \r
227         void setGranularity(float f) {\r
228                 granularity = f;\r
229         }\r
230 \r
231         float getGranularity() {\r
232                 return granularity;\r
233         }\r
234 \r
235         int numPoints() {\r
236                 return controlPoints.Num();\r
237         }\r
238 \r
239         idVec3 *getPoint(int index) {\r
240                 assert(index >= 0 && index < controlPoints.Num());\r
241                 return controlPoints[index];\r
242         }\r
243 \r
244         idVec3 *getSegmentPoint(int index) {\r
245                 assert(index >= 0 && index < splinePoints.Num());\r
246                 return splinePoints[index];\r
247         }\r
248 \r
249 \r
250         void setSegmentTime(int index, int time) {\r
251                 assert(index >= 0 && index < splinePoints.Num());\r
252                 splineTime[index] = time;\r
253         }\r
254 \r
255         int getSegmentTime(int index) {\r
256                 assert(index >= 0 && index < splinePoints.Num());\r
257                 return (int)splineTime[index];\r
258         }\r
259         void addSegmentTime(int index, int time) {\r
260                 assert(index >= 0 && index < splinePoints.Num());\r
261                 splineTime[index] += time;\r
262         }\r
263 \r
264         float totalDistance();\r
265 \r
266         static idVec3 zero;\r
267 \r
268         int getActiveSegment() {\r
269                 return activeSegment;\r
270         }\r
271 \r
272         void setActiveSegment(int i) {\r
273                 //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));\r
274                 activeSegment = i;\r
275         }\r
276 \r
277         int numSegments() {\r
278                 return splinePoints.Num();\r
279         }\r
280 \r
281         void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {\r
282                 pathColor = path;\r
283                 segmentColor = segment;\r
284                 controlColor = control;\r
285                 activeColor = active;\r
286         }\r
287 \r
288         const char *getName() {\r
289                 return name.c_str();\r
290         }\r
291 \r
292         void setName(const char *p) {\r
293                 name = p;\r
294         }\r
295 \r
296         bool validTime() {\r
297                 if (dirty) {\r
298                         buildSpline();\r
299                 }\r
300                 // gcc doesn't allow static casting away from bools\r
301                 // why?  I've no idea...\r
302                 return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());\r
303         }\r
304 \r
305         void setTime(long t) {\r
306                 time = t;\r
307         }\r
308 \r
309         void setBaseTime(long t) {\r
310                 baseTime = t;\r
311         }\r
312 \r
313 protected:\r
314         idStr name;\r
315         float calcSpline(int step, float tension);\r
316         idList<idVec3*> controlPoints;\r
317         idList<idVec3*> splinePoints;\r
318         idList<double> splineTime;\r
319         idVec3 *selected;\r
320         idVec3 pathColor, segmentColor, controlColor, activeColor;\r
321         float granularity;\r
322         bool editMode;\r
323         bool dirty;\r
324         int activeSegment;\r
325         long baseTime;\r
326         long time;\r
327         friend class idCamera;\r
328 };\r
329 \r
330 // time in milliseconds \r
331 // velocity where 1.0 equal rough walking speed\r
332 struct idVelocity {\r
333         idVelocity(long start, long duration, float s) {\r
334                 startTime = start;\r
335                 time = duration;\r
336                 speed = s;\r
337         }\r
338         long    startTime;\r
339         long    time;\r
340         float   speed;\r
341 };\r
342 \r
343 // can either be a look at or origin position for a camera\r
344 // \r
345 class idCameraPosition : public idPointListInterface {\r
346 public:\r
347         \r
348         virtual void clearVelocities() {\r
349                 for (int i = 0; i < velocities.Num(); i++) {\r
350                         delete velocities[i];\r
351                         velocities[i] = NULL;\r
352                 }\r
353                 velocities.Clear();\r
354         }\r
355 \r
356         virtual void clear() {\r
357                 editMode = false;\r
358                 clearVelocities();\r
359         }\r
360 \r
361         idCameraPosition(const char *p) {\r
362                 name = p;\r
363         }\r
364 \r
365         idCameraPosition() {\r
366                 time = 0;\r
367                 name = "position";\r
368         }\r
369 \r
370         idCameraPosition(long t) {\r
371                 time = t;\r
372         }\r
373 \r
374         virtual ~idCameraPosition() {\r
375                 clear();\r
376         }\r
377 \r
378         \r
379         // this can be done with RTTI syntax but i like the derived classes setting a type\r
380         // makes serialization a bit easier to see\r
381         //\r
382         enum positionType {\r
383                 FIXED = 0x00,\r
384                 INTERPOLATED,\r
385                 SPLINE,\r
386                 POSITION_COUNT\r
387         };\r
388 \r
389 \r
390         virtual void start(long t) {\r
391                 startTime = t;\r
392         }\r
393 \r
394         long getTime() {\r
395                 return time;\r
396         }\r
397 \r
398         virtual void setTime(long t) {\r
399                 time = t;\r
400         }\r
401 \r
402         float getBaseVelocity() {\r
403                 return baseVelocity;\r
404         }\r
405 \r
406         float getVelocity(long t) {\r
407                 long check = t - startTime;\r
408                 for (int i = 0; i < velocities.Num(); i++) {\r
409                         if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {\r
410                                 return velocities[i]->speed;\r
411                         }\r
412                 }\r
413                 return baseVelocity;\r
414         }\r
415 \r
416         void addVelocity(long start, long duration, float speed) {\r
417                 velocities.Append(new idVelocity(start, duration, speed));\r
418         }\r
419 \r
420         virtual const idVec3 *getPosition(long t) { \r
421                 assert(true);\r
422                 return NULL;\r
423         }\r
424 \r
425         virtual void draw(bool editMode) {};\r
426 \r
427         virtual void parse(const char *(*text)) {};\r
428         virtual void write(fileHandle_t file, const char *name);\r
429         virtual bool parseToken(const char *key, const char *(*text));\r
430 \r
431         const char *getName() {\r
432                 return name.c_str();\r
433         }\r
434 \r
435         void setName(const char *p) {\r
436                 name = p;\r
437         }\r
438 \r
439         virtual void startEdit() {\r
440                 editMode = true;\r
441         }\r
442 \r
443         virtual void stopEdit() {\r
444                 editMode = false;\r
445         }\r
446 \r
447         virtual void draw() {};\r
448 \r
449         const char *typeStr() {\r
450                 return positionStr[static_cast<int>(type)];\r
451         }\r
452 \r
453         void calcVelocity(float distance) {\r
454                 float secs = (float)time / 1000;\r
455                 baseVelocity = distance / secs;\r
456         }\r
457 \r
458 protected:\r
459         static const char* positionStr[POSITION_COUNT];\r
460         long            startTime;\r
461         long            time;\r
462         idCameraPosition::positionType type;\r
463         idStr           name;\r
464         bool    editMode;\r
465         idList<idVelocity*> velocities;\r
466         float           baseVelocity;\r
467 };\r
468 \r
469 class idFixedPosition : public idCameraPosition {\r
470 public:\r
471 \r
472         void init() {\r
473                 pos.Zero();\r
474                 type = idCameraPosition::FIXED;\r
475         }\r
476         \r
477         idFixedPosition() : idCameraPosition() {\r
478                 init();\r
479         }\r
480         \r
481         idFixedPosition(idVec3 p) : idCameraPosition() {\r
482                 init();\r
483                 pos = p;\r
484         }\r
485 \r
486         virtual void addPoint(const idVec3 &v) {\r
487                 pos = v;\r
488         }\r
489         \r
490         virtual void addPoint(const float x, const float y, const float z) {\r
491                 pos.set(x, y, z);\r
492         }\r
493 \r
494 \r
495         ~idFixedPosition() {\r
496         }\r
497 \r
498         virtual const idVec3 *getPosition(long t) { \r
499                 return &pos;\r
500         }\r
501 \r
502         void parse(const char *(*text));\r
503         void write(fileHandle_t file, const char *name);\r
504 \r
505         virtual int numPoints() {\r
506                 return 1;\r
507         }\r
508 \r
509         virtual idVec3 *getPoint(int index) {\r
510                 if (index != 0) {\r
511                         assert(true);\r
512                 };\r
513                 return &pos;\r
514         }\r
515 \r
516         virtual void draw(bool editMode) {\r
517                 glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");\r
518         }\r
519 \r
520 protected:\r
521         idVec3 pos;\r
522 };\r
523 \r
524 class idInterpolatedPosition : public idCameraPosition {\r
525 public:\r
526 \r
527         void init() {\r
528                 type = idCameraPosition::INTERPOLATED;\r
529                 first = true;\r
530                 startPos.Zero();\r
531                 endPos.Zero();\r
532         }\r
533         \r
534         idInterpolatedPosition() : idCameraPosition() {\r
535                 init();\r
536         }\r
537         \r
538         idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {\r
539                 init();\r
540                 startPos = start;\r
541                 endPos = end;\r
542         }\r
543 \r
544         ~idInterpolatedPosition() {\r
545         }\r
546 \r
547         virtual const idVec3 *getPosition(long t);\r
548 \r
549         void parse(const char *(*text));\r
550         void write(fileHandle_t file, const char *name);\r
551 \r
552         virtual int numPoints() {\r
553                 return 2;\r
554         }\r
555 \r
556         virtual idVec3 *getPoint(int index) {\r
557                 assert(index >= 0 && index < 2);\r
558                 if (index == 0) {\r
559                         return &startPos;\r
560                 }\r
561                 return &endPos;\r
562         }\r
563 \r
564         virtual void addPoint(const float x, const float y, const float z) {\r
565                 if (first) {\r
566                         startPos.set(x, y, z);\r
567                         first = false;\r
568                 } else {\r
569                         endPos.set(x, y, z);\r
570                         first = true;\r
571                 }\r
572         }\r
573 \r
574         virtual void addPoint(const idVec3 &v) {\r
575                 if (first) {\r
576                         startPos = v;\r
577                         first = false;\r
578                 } else {\r
579                         endPos = v;\r
580                         first = true;\r
581                 }\r
582         }\r
583 \r
584         virtual void draw(bool editMode) {\r
585                 glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");\r
586                 glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");\r
587                 qglBegin(GL_LINES);\r
588                 qglVertex3fv(startPos);\r
589                 qglVertex3fv(endPos);\r
590                 qglEnd();\r
591         }\r
592 \r
593         virtual void start(long t) {\r
594                 idCameraPosition::start(t);\r
595                 lastTime = startTime;\r
596                 distSoFar = 0.0;\r
597                 idVec3 temp = startPos;\r
598                 temp -= endPos;\r
599                 calcVelocity(temp.Length());\r
600         }\r
601 \r
602 protected:\r
603         bool first;\r
604         idVec3 startPos;\r
605         idVec3 endPos;\r
606         long lastTime;\r
607         float distSoFar;\r
608 };\r
609 \r
610 class idSplinePosition : public idCameraPosition {\r
611 public:\r
612 \r
613         void init() {\r
614                 type = idCameraPosition::SPLINE;\r
615         }\r
616         \r
617         idSplinePosition() : idCameraPosition() {\r
618                 init();\r
619         }\r
620         \r
621         idSplinePosition(long time) : idCameraPosition(time) {\r
622                 init();\r
623         }\r
624 \r
625         ~idSplinePosition() {\r
626         }\r
627 \r
628         virtual void start(long t) {\r
629                 idCameraPosition::start(t);\r
630                 target.initPosition(t, time);\r
631                 lastTime = startTime;\r
632                 distSoFar = 0.0;\r
633                 calcVelocity(target.totalDistance());\r
634         }\r
635 \r
636         //virtual const idVec3 *getPosition(long t) { \r
637         //      return target.getPosition(t);\r
638         //}\r
639         virtual const idVec3 *getPosition(long t);\r
640 \r
641 \r
642         //virtual const idVec3 *getPosition(long t) const { \r
643 \r
644         void addControlPoint(idVec3 &v) {\r
645                 target.addPoint(v);\r
646         }\r
647 \r
648         void parse(const char *(*text));\r
649         void write(fileHandle_t file, const char *name);\r
650 \r
651         virtual int numPoints() {\r
652                 return target.numPoints();\r
653         }\r
654 \r
655         virtual idVec3 *getPoint(int index) {\r
656                 return target.getPoint(index);\r
657         }\r
658 \r
659         virtual void addPoint(const idVec3 &v) {\r
660                 target.addPoint(v);\r
661         }\r
662 \r
663         virtual void addPoint(const float x, const float y, const float z) {\r
664                 target.addPoint(x, y, z);\r
665         }\r
666 \r
667         virtual void draw(bool editMode) {\r
668                 target.draw(editMode);\r
669         }\r
670 \r
671         virtual void updateSelection(const idVec3 &move) {\r
672                 idCameraPosition::updateSelection(move);\r
673                 target.buildSpline();\r
674         }\r
675 \r
676 protected:\r
677         idSplineList target;\r
678         long lastTime;\r
679         float distSoFar;\r
680 };\r
681 \r
682 class idCameraFOV {\r
683 public:\r
684         \r
685         idCameraFOV() {\r
686                 time = 0;\r
687                 length = 0;\r
688                 fov = 90;\r
689         }\r
690 \r
691         idCameraFOV(int v) {\r
692                 time = 0;\r
693                 length = 0;\r
694                 fov = v;\r
695         }\r
696 \r
697         idCameraFOV(int s, int e, long t) {\r
698                 startFOV = s;\r
699                 endFOV = e;\r
700                 length = t;\r
701         }\r
702 \r
703 \r
704         ~idCameraFOV(){}\r
705 \r
706         void setFOV(float f) {\r
707                 fov = f;\r
708         }\r
709 \r
710         float getFOV(long t) {\r
711                 if (length) {\r
712                         float percent = (t - startTime) / length;\r
713                         if (percent < 0.0) {\r
714                                 percent = 0.0;\r
715                         } else if (percent > 1.0) {\r
716                                 percent = 1.0;\r
717                         }\r
718                         float temp = endFOV - startFOV;\r
719                         temp *= percent;\r
720                         fov = startFOV + temp;\r
721 \r
722                         if (percent == 1.0) {\r
723                                 length = 0.0;\r
724                         }\r
725                 }\r
726                 return fov;\r
727         }\r
728 \r
729         void start(long t) {\r
730                 startTime = t;\r
731         }\r
732 \r
733         void reset(float startfov, float endfov, int start, float len) {\r
734                 startFOV = startfov;\r
735                 endFOV = endfov;\r
736                 startTime = start;\r
737                 length = len * 1000;\r
738         }\r
739 \r
740         void parse(const char *(*text));\r
741         void write(fileHandle_t file, const char *name);\r
742 \r
743 protected:\r
744         float fov;\r
745         float startFOV;\r
746         float endFOV;\r
747         int startTime;\r
748         int time;\r
749         float length;\r
750 };\r
751 \r
752 \r
753 \r
754 \r
755 class idCameraEvent {\r
756 public:                                         // parameters\r
757         enum eventType {\r
758                 EVENT_NA = 0x00,\r
759                 EVENT_WAIT,                     // \r
760                 EVENT_TARGETWAIT,       // \r
761                 EVENT_SPEED,            // \r
762                 EVENT_TARGET,           // char(name)\r
763                 EVENT_SNAPTARGET,       // \r
764                 EVENT_FOV,                      // int(time), int(targetfov)\r
765                 EVENT_CMD,                      // \r
766                 EVENT_TRIGGER,          // \r
767                 EVENT_STOP,                     // \r
768                 EVENT_CAMERA,           // \r
769                 EVENT_FADEOUT,          // int(time)\r
770                 EVENT_FADEIN,           // int(time)\r
771                 EVENT_FEATHER,          // \r
772                 EVENT_COUNT                     \r
773         };\r
774 \r
775         static const char* eventStr[EVENT_COUNT];\r
776 \r
777         idCameraEvent() {\r
778                 paramStr = "";\r
779                 type = EVENT_NA;\r
780                 time = 0;\r
781         }\r
782 \r
783         idCameraEvent(eventType t, const char *param, long n) {\r
784                 type = t;\r
785                 paramStr = param;\r
786                 time = n;\r
787         }\r
788 \r
789         ~idCameraEvent() {};\r
790 \r
791         eventType getType() {\r
792                 return type;\r
793         }\r
794 \r
795         const char *typeStr() {\r
796                 return eventStr[static_cast<int>(type)];\r
797         }\r
798 \r
799         const char *getParam() {\r
800                 return paramStr.c_str();\r
801         }\r
802 \r
803         long getTime() {\r
804                 return time;\r
805         }\r
806 \r
807         void setTime(long n) {\r
808                 time = n;\r
809         }\r
810 \r
811         void parse(const char *(*text));\r
812         void write(fileHandle_t file, const char *name);\r
813 \r
814         void setTriggered(bool b) {\r
815                 triggered = b;\r
816         }\r
817 \r
818         bool getTriggered() {\r
819                 return triggered;\r
820         }\r
821 \r
822 protected:\r
823         eventType type;\r
824         idStr paramStr;\r
825         long time;\r
826         bool triggered;\r
827 \r
828 };\r
829 \r
830 class idCameraDef {\r
831 public:\r
832 \r
833         void clear() {\r
834                 currentCameraPosition = 0;\r
835                 cameraRunning = false;\r
836                 lastDirection.Zero();\r
837                 baseTime = 30;\r
838                 activeTarget = 0;\r
839                 name = "camera01";\r
840                 fov.setFOV(90);\r
841                 int i;\r
842                 for (i = 0; i < targetPositions.Num(); i++) {\r
843                         delete targetPositions[i];\r
844                 }\r
845                 for (i = 0; i < events.Num(); i++) {\r
846                         delete events[i];\r
847                 }\r
848                 delete cameraPosition;\r
849                 cameraPosition = NULL;\r
850                 events.Clear();\r
851                 targetPositions.Clear();\r
852         }\r
853 \r
854         idCameraPosition *startNewCamera(idCameraPosition::positionType type) {\r
855                 clear();\r
856                 if (type == idCameraPosition::SPLINE) {\r
857                         cameraPosition = new idSplinePosition();\r
858                 } else if (type == idCameraPosition::INTERPOLATED) {\r
859                         cameraPosition = new idInterpolatedPosition();\r
860                 } else {\r
861                         cameraPosition = new idFixedPosition();\r
862                 }\r
863                 return cameraPosition;\r
864         }\r
865 \r
866         idCameraDef() {\r
867                 cameraPosition = NULL;\r
868                 clear();\r
869         }\r
870 \r
871         ~idCameraDef() {\r
872                 clear();\r
873         }\r
874 \r
875         void addEvent(idCameraEvent::eventType t, const char *param, long time);\r
876 \r
877         void addEvent(idCameraEvent *event);\r
878 \r
879         void removeEvent( int index);\r
880 \r
881         static int sortEvents(const void *p1, const void *p2);\r
882 \r
883         int numEvents() {\r
884                 return events.Num();\r
885         }\r
886 \r
887         idCameraEvent *getEvent(int index) {\r
888                 assert(index >= 0 && index < events.Num());\r
889                 return events[index];\r
890         }\r
891 \r
892         void parse(const char *(*text));\r
893         bool load(const char *filename);\r
894         void save(const char *filename);\r
895 \r
896         void buildCamera();\r
897 \r
898         //idSplineList *getcameraPosition() {\r
899         //      return &cameraPosition;\r
900         //}\r
901 \r
902         static idCameraPosition *newFromType(idCameraPosition::positionType t) {\r
903                 switch (t) {\r
904                         case idCameraPosition::FIXED : return new idFixedPosition();\r
905                         case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();\r
906                         case idCameraPosition::SPLINE : return new idSplinePosition();\r
907       default:\r
908         break;\r
909                 };\r
910                 return NULL;\r
911         }\r
912 \r
913         void addTarget(const char *name, idCameraPosition::positionType type);\r
914 \r
915         idCameraPosition *getActiveTarget() {\r
916                 if (targetPositions.Num() == 0) {\r
917                         addTarget(NULL, idCameraPosition::FIXED);\r
918                 }\r
919                 return targetPositions[activeTarget];\r
920         }\r
921 \r
922         idCameraPosition *getActiveTarget(int index) {\r
923                 if (targetPositions.Num() == 0) {\r
924                         addTarget(NULL, idCameraPosition::FIXED);\r
925                         return targetPositions[0];\r
926                 }\r
927                 return targetPositions[index];\r
928         }\r
929 \r
930         int numTargets() {\r
931                 return targetPositions.Num();\r
932         }\r
933 \r
934 \r
935         void setActiveTargetByName(const char *name) {\r
936                 for (int i = 0; i < targetPositions.Num(); i++) {\r
937                         if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {\r
938                                 setActiveTarget(i);\r
939                                 return;\r
940                         }\r
941                 }\r
942         }\r
943 \r
944         void setActiveTarget(int index) {\r
945                 assert(index >= 0 && index < targetPositions.Num());\r
946                 activeTarget = index;\r
947         }\r
948 \r
949         void setRunning(bool b) {\r
950                 cameraRunning = b;\r
951         }\r
952 \r
953         void setBaseTime(float f) {\r
954                 baseTime = f;\r
955         }\r
956 \r
957         float getBaseTime() {\r
958                 return baseTime;\r
959         }\r
960 \r
961         float getTotalTime() {\r
962                 return totalTime;\r
963         }\r
964         \r
965         void startCamera(long t);\r
966         void stopCamera() {\r
967                 cameraRunning = true;\r
968         }\r
969         void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);\r
970 \r
971         bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);\r
972         bool getCameraInfo(long time, float *origin, float *direction, float *fv) {\r
973                 idVec3 org, dir;\r
974                 org[0] = origin[0];\r
975                 org[1] = origin[1];\r
976                 org[2] = origin[2];\r
977                 dir[0] = direction[0];\r
978                 dir[1] = direction[1];\r
979                 dir[2] = direction[2];\r
980                 bool b = getCameraInfo(time, org, dir, fv);\r
981                 origin[0] = org[0];\r
982                 origin[1] = org[1];\r
983                 origin[2] = org[2];\r
984                 direction[0] = dir[0];\r
985                 direction[1] = dir[1];\r
986                 direction[2] = dir[2];\r
987                 return b;\r
988         }\r
989 \r
990         void draw(bool editMode) {\r
991                 // gcc doesn't allow casting away from bools\r
992                 // why?  I've no idea...\r
993                 if (cameraPosition) {\r
994                         cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));\r
995                         int count = targetPositions.Num();\r
996                         for (int i = 0; i < count; i++) {\r
997                                 targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));\r
998                         }\r
999                 }\r
1000         }\r
1001 \r
1002 /*\r
1003         int numSegments() {\r
1004                 if (cameraEdit) {\r
1005                         return cameraPosition.numSegments();\r
1006                 }\r
1007                 return getTargetSpline()->numSegments();\r
1008         }\r
1009 \r
1010         int getActiveSegment() {\r
1011                 if (cameraEdit) {\r
1012                         return cameraPosition.getActiveSegment();\r
1013                 }\r
1014                 return getTargetSpline()->getActiveSegment();\r
1015         }\r
1016 \r
1017         void setActiveSegment(int i) {\r
1018                 if (cameraEdit) {\r
1019                         cameraPosition.setActiveSegment(i);\r
1020                 } else {\r
1021                         getTargetSpline()->setActiveSegment(i);\r
1022                 }\r
1023         }\r
1024 */\r
1025         int numPoints() {\r
1026                 if (cameraEdit) {\r
1027                         return cameraPosition->numPoints();\r
1028                 }\r
1029                 return getActiveTarget()->numPoints();\r
1030         }\r
1031 \r
1032         const idVec3 *getPoint(int index) {\r
1033                 if (cameraEdit) {\r
1034                         return cameraPosition->getPoint(index);\r
1035                 }\r
1036                 return getActiveTarget()->getPoint(index);\r
1037         }\r
1038 \r
1039         void stopEdit() {\r
1040                 editMode = false;\r
1041                 if (cameraEdit) {\r
1042                         cameraPosition->stopEdit();\r
1043                 } else {\r
1044                         getActiveTarget()->stopEdit();\r
1045                 }\r
1046         }\r
1047 \r
1048         void startEdit(bool camera) {\r
1049                 cameraEdit = camera;\r
1050                 if (camera) {\r
1051                         cameraPosition->startEdit();\r
1052                         for (int i = 0; i < targetPositions.Num(); i++) {\r
1053                                 targetPositions[i]->stopEdit();\r
1054                         }\r
1055                 } else {\r
1056                         getActiveTarget()->startEdit();\r
1057                         cameraPosition->stopEdit();\r
1058                 }\r
1059                 editMode = true;\r
1060         }\r
1061 \r
1062         bool waitEvent(int index);\r
1063 \r
1064         const char *getName() {\r
1065                 return name.c_str();\r
1066         }\r
1067 \r
1068         void setName(const char *p) {\r
1069                 name = p;\r
1070         }\r
1071 \r
1072         idCameraPosition *getPositionObj() {\r
1073                 if (cameraPosition == NULL) {\r
1074                         cameraPosition = new idFixedPosition();\r
1075                 }\r
1076                 return cameraPosition;\r
1077         }\r
1078 \r
1079 protected:\r
1080         idStr name;\r
1081         int currentCameraPosition;\r
1082         idVec3 lastDirection;\r
1083         bool cameraRunning;\r
1084         idCameraPosition *cameraPosition;\r
1085         idList<idCameraPosition*> targetPositions;\r
1086         idList<idCameraEvent*> events;\r
1087         idCameraFOV fov;\r
1088         int activeTarget;\r
1089         float totalTime;\r
1090         float baseTime;\r
1091         long startTime;\r
1092 \r
1093         bool cameraEdit;\r
1094         bool editMode;\r
1095 };\r
1096 \r
1097 extern bool g_splineMode;\r
1098 \r
1099 extern idCameraDef *g_splineList;\r
1100 \r
1101 \r
1102 #endif\r