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