2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but 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.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "util_list.h"
33 #include "math_vector.h"
35 typedef int fileHandle_t;
37 extern void glBox(idVec3 &color, idVec3 &point, float size);
38 extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);
40 static idVec4 blue(0, 0, 1, 1);
41 static idVec4 red(1, 0, 0, 1);
43 class idPointListInterface {
45 idPointListInterface() {
46 selectedPoints.Clear();
48 virtual ~idPointListInterface() {};
50 virtual int numPoints() {
54 virtual void addPoint(const float x, const float y, const float z) {}
55 virtual void addPoint(const idVec3 &v) {}
56 virtual void removePoint(int index) {}
57 virtual idVec3 *getPoint(int index) { return NULL; }
59 int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
60 idVec3 origin(ox, oy, oz);
61 idVec3 dir(dx, dy, dz);
62 return selectPointByRay(origin, dir, single);
65 int selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {
70 // find the point closest to the ray
75 for (i=0; i < count; i++) {
79 d = DotProduct(temp, direction);
80 __VectorMA (origin, d, direction, temp);
90 selectPoint(besti, single);
96 int isPointSelected(int index) {
97 int count = selectedPoints.Num();
98 for (int i = 0; i < count; i++) {
99 if (selectedPoints[i] == index) {
106 int selectPoint(int index, bool single) {
107 if (index >= 0 && index < numPoints()) {
111 if (isPointSelected(index) >= 0) {
112 selectedPoints.Remove(index);
115 return selectedPoints.Append(index);
121 selectedPoints.Clear();
122 for (int i = 0; i < numPoints(); i++) {
123 selectedPoints.Append(i);
128 selectedPoints.Clear();
131 int numSelectedPoints();
133 idVec3 *getSelectedPoint(int index) {
134 assert(index >= 0 && index < numSelectedPoints());
135 return getPoint(selectedPoints[index]);
138 virtual void updateSelection(float x, float y, float z) {
139 idVec3 move(x, y, z);
140 updateSelection(move);
143 virtual void updateSelection(const idVec3 &move) {
144 int count = selectedPoints.Num();
145 for (int i = 0; i < count; i++) {
146 *getPoint(selectedPoints[i]) += move;
150 void drawSelection() {
151 int count = selectedPoints.Num();
152 for (int i = 0; i < count; i++) {
153 glBox(red, *getPoint(selectedPoints[i]), 4);
158 idList<int> selectedPoints;
171 idSplineList(const char *p) {
180 void clearControl() {
181 for (int i = 0; i < controlPoints.Num(); i++) {
182 delete controlPoints[i];
184 controlPoints.Clear();
188 for (int i = 0; i < splinePoints.Num(); i++) {
189 delete splinePoints[i];
191 splinePoints.Clear();
194 void parse(const char *(*text));
195 void write(fileHandle_t file, const char *name);
204 granularity = 0.025f;
205 pathColor.set(1.0f, 0.5f, 0.0f);
206 controlColor.set(0.7f, 0.0f, 1.0f);
207 segmentColor.set(0.0f, 0.0f, 1.0f);
208 activeColor.set(1.0f, 0.0f, 0.0f);
211 void initPosition(long startTime, long totalTime);
212 const idVec3 *getPosition(long time);
215 void draw(bool editMode);
216 void addToRenderer();
218 void setSelectedPoint(idVec3 *p);
219 idVec3 *getSelectedPoint() {
223 void addPoint(const idVec3 &v) {
224 controlPoints.Append(new idVec3(v));
228 void addPoint(float x, float y, float z) {
229 controlPoints.Append(new idVec3(x, y, z));
233 void updateSelection(const idVec3 &move);
245 void setGranularity(float f) {
249 float getGranularity() {
254 return controlPoints.Num();
257 idVec3 *getPoint(int index) {
258 assert(index >= 0 && index < controlPoints.Num());
259 return controlPoints[index];
262 idVec3 *getSegmentPoint(int index) {
263 assert(index >= 0 && index < splinePoints.Num());
264 return splinePoints[index];
268 void setSegmentTime(int index, int time) {
269 assert(index >= 0 && index < splinePoints.Num());
270 splineTime[index] = time;
273 int getSegmentTime(int index) {
274 assert(index >= 0 && index < splinePoints.Num());
275 return (int)splineTime[index];
277 void addSegmentTime(int index, int time) {
278 assert(index >= 0 && index < splinePoints.Num());
279 splineTime[index] += time;
282 float totalDistance();
286 int getActiveSegment() {
287 return activeSegment;
290 void setActiveSegment(int i) {
291 //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
296 return splinePoints.Num();
299 void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {
301 segmentColor = segment;
302 controlColor = control;
303 activeColor = active;
306 const char *getName() {
310 void setName(const char *p) {
318 // gcc doesn't allow static casting away from bools
319 // why? I've no idea...
320 return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
323 void setTime(long t) {
327 void setBaseTime(long t) {
333 float calcSpline(int step, float tension);
334 idList<idVec3*> controlPoints;
335 idList<idVec3*> splinePoints;
336 idList<double> splineTime;
338 idVec3 pathColor, segmentColor, controlColor, activeColor;
345 friend class idCamera;
348 // time in milliseconds
349 // velocity where 1.0 equal rough walking speed
351 idVelocity(long start, long duration, float s) {
361 // can either be a look at or origin position for a camera
363 class idCameraPosition : public idPointListInterface {
366 virtual void clearVelocities() {
367 for (int i = 0; i < velocities.Num(); i++) {
368 delete velocities[i];
369 velocities[i] = NULL;
374 virtual void clear() {
379 idCameraPosition(const char *p) {
388 idCameraPosition(long t) {
392 virtual ~idCameraPosition() {
397 // this can be done with RTTI syntax but i like the derived classes setting a type
398 // makes serialization a bit easier to see
408 virtual void start(long t) {
416 virtual void setTime(long t) {
420 float getBaseVelocity() {
424 float getVelocity(long t) {
425 long check = t - startTime;
426 for (int i = 0; i < velocities.Num(); i++) {
427 if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
428 return velocities[i]->speed;
434 void addVelocity(long start, long duration, float speed) {
435 velocities.Append(new idVelocity(start, duration, speed));
438 virtual const idVec3 *getPosition(long t) {
443 virtual void draw(bool editMode) {};
445 virtual void parse(const char *(*text)) {};
446 virtual void write(fileHandle_t file, const char *name);
447 virtual bool parseToken(const char *key, const char *(*text));
449 const char *getName() {
453 void setName(const char *p) {
457 virtual void startEdit() {
461 virtual void stopEdit() {
465 virtual void draw() {};
467 const char *typeStr() {
468 return positionStr[static_cast<int>(type)];
471 void calcVelocity(float distance) {
472 float secs = (float)time / 1000;
473 baseVelocity = distance / secs;
477 static const char* positionStr[POSITION_COUNT];
480 idCameraPosition::positionType type;
483 idList<idVelocity*> velocities;
487 class idFixedPosition : public idCameraPosition {
492 type = idCameraPosition::FIXED;
495 idFixedPosition() : idCameraPosition() {
499 idFixedPosition(idVec3 p) : idCameraPosition() {
504 virtual void addPoint(const idVec3 &v) {
508 virtual void addPoint(const float x, const float y, const float z) {
516 virtual const idVec3 *getPosition(long t) {
520 void parse(const char *(*text));
521 void write(fileHandle_t file, const char *name);
523 virtual int numPoints() {
527 virtual idVec3 *getPoint(int index) {
534 virtual void draw(bool editMode) {
535 glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
542 class idInterpolatedPosition : public idCameraPosition {
546 type = idCameraPosition::INTERPOLATED;
552 idInterpolatedPosition() : idCameraPosition() {
556 idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {
562 ~idInterpolatedPosition() {
565 virtual const idVec3 *getPosition(long t);
567 void parse(const char *(*text));
568 void write(fileHandle_t file, const char *name);
570 virtual int numPoints() {
574 virtual idVec3 *getPoint(int index) {
575 assert(index >= 0 && index < 2);
582 virtual void addPoint(const float x, const float y, const float z) {
584 startPos.set(x, y, z);
592 virtual void addPoint(const idVec3 &v) {
602 virtual void draw(bool editMode) {
603 glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
604 glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
606 glVertex3fv(startPos);
611 virtual void start(long t) {
612 idCameraPosition::start(t);
613 lastTime = startTime;
615 idVec3 temp = startPos;
617 calcVelocity(temp.Length());
628 class idSplinePosition : public idCameraPosition {
632 type = idCameraPosition::SPLINE;
635 idSplinePosition() : idCameraPosition() {
639 idSplinePosition(long time) : idCameraPosition(time) {
643 ~idSplinePosition() {
646 virtual void start(long t) {
647 idCameraPosition::start(t);
648 target.initPosition(t, time);
649 lastTime = startTime;
651 calcVelocity(target.totalDistance());
654 //virtual const idVec3 *getPosition(long t) {
655 // return target.getPosition(t);
657 virtual const idVec3 *getPosition(long t);
660 //virtual const idVec3 *getPosition(long t) const {
662 void addControlPoint(idVec3 &v) {
666 void parse(const char *(*text));
667 void write(fileHandle_t file, const char *name);
669 virtual int numPoints() {
670 return target.numPoints();
673 virtual idVec3 *getPoint(int index) {
674 return target.getPoint(index);
677 virtual void addPoint(const idVec3 &v) {
681 virtual void addPoint(const float x, const float y, const float z) {
682 target.addPoint(x, y, z);
685 virtual void draw(bool editMode) {
686 target.draw(editMode);
689 virtual void updateSelection(const idVec3 &move) {
690 idCameraPosition::updateSelection(move);
691 target.buildSpline();
715 idCameraFOV(int s, int e, long t) {
724 void setFOV(float f) {
728 float getFOV(long t) {
730 float percent = (t - startTime) / length;
733 } else if (percent > 1.0) {
736 float temp = endFOV - startFOV;
738 fov = startFOV + temp;
740 if (percent == 1.0) {
751 void reset(float startfov, float endfov, int start, float len) {
758 void parse(const char *(*text));
759 void write(fileHandle_t file, const char *name);
773 class idCameraEvent {
774 public: // parameters
780 EVENT_TARGET, // char(name)
782 EVENT_FOV, // int(time), int(targetfov)
787 EVENT_FADEOUT, // int(time)
788 EVENT_FADEIN, // int(time)
793 static const char* eventStr[EVENT_COUNT];
801 idCameraEvent(eventType t, const char *param, long n) {
809 eventType getType() {
813 const char *typeStr() {
814 return eventStr[static_cast<int>(type)];
817 const char *getParam() {
818 return paramStr.c_str();
825 void setTime(long n) {
829 void parse(const char *(*text));
830 void write(fileHandle_t file, const char *name);
832 void setTriggered(bool b) {
836 bool getTriggered() {
852 currentCameraPosition = 0;
853 cameraRunning = false;
854 lastDirection.Zero();
860 for (i = 0; i < targetPositions.Num(); i++) {
861 delete targetPositions[i];
863 for (i = 0; i < events.Num(); i++) {
866 delete cameraPosition;
867 cameraPosition = NULL;
869 targetPositions.Clear();
872 idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
874 if (type == idCameraPosition::SPLINE) {
875 cameraPosition = new idSplinePosition();
876 } else if (type == idCameraPosition::INTERPOLATED) {
877 cameraPosition = new idInterpolatedPosition();
879 cameraPosition = new idFixedPosition();
881 return cameraPosition;
885 cameraPosition = NULL;
893 void addEvent(idCameraEvent::eventType t, const char *param, long time);
895 void addEvent(idCameraEvent *event);
897 void removeEvent( int index);
899 static int sortEvents(const void *p1, const void *p2);
905 idCameraEvent *getEvent(int index) {
906 assert(index >= 0 && index < events.Num());
907 return events[index];
910 void parse(const char *(*text));
911 bool load(const char *filename);
912 void save(const char *filename);
916 //idSplineList *getcameraPosition() {
917 // return &cameraPosition;
920 static idCameraPosition *newFromType(idCameraPosition::positionType t) {
922 case idCameraPosition::FIXED : return new idFixedPosition();
923 case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
924 case idCameraPosition::SPLINE : return new idSplinePosition();
931 void addTarget(const char *name, idCameraPosition::positionType type);
933 idCameraPosition *getActiveTarget() {
934 if (targetPositions.Num() == 0) {
935 addTarget(NULL, idCameraPosition::FIXED);
937 return targetPositions[activeTarget];
940 idCameraPosition *getActiveTarget(int index) {
941 if (targetPositions.Num() == 0) {
942 addTarget(NULL, idCameraPosition::FIXED);
943 return targetPositions[0];
945 return targetPositions[index];
949 return targetPositions.Num();
953 void setActiveTargetByName(const char *name) {
954 for (int i = 0; i < targetPositions.Num(); i++) {
955 if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
962 void setActiveTarget(int index) {
963 assert(index >= 0 && index < targetPositions.Num());
964 activeTarget = index;
967 void setRunning(bool b) {
971 void setBaseTime(float f) {
975 float getBaseTime() {
979 float getTotalTime() {
983 void startCamera(long t);
985 cameraRunning = true;
987 void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);
989 bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);
990 bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
995 dir[0] = direction[0];
996 dir[1] = direction[1];
997 dir[2] = direction[2];
998 bool b = getCameraInfo(time, org, dir, fv);
1002 direction[0] = dir[0];
1003 direction[1] = dir[1];
1004 direction[2] = dir[2];
1008 void draw(bool editMode) {
1009 // gcc doesn't allow casting away from bools
1010 // why? I've no idea...
1011 if (cameraPosition) {
1012 cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
1013 int count = targetPositions.Num();
1014 for (int i = 0; i < count; i++) {
1015 targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
1023 return cameraPosition.numSegments();
1025 return getTargetSpline()->numSegments();
1028 int getActiveSegment() {
1030 return cameraPosition.getActiveSegment();
1032 return getTargetSpline()->getActiveSegment();
1035 void setActiveSegment(int i) {
1037 cameraPosition.setActiveSegment(i);
1039 getTargetSpline()->setActiveSegment(i);
1045 return cameraPosition->numPoints();
1047 return getActiveTarget()->numPoints();
1050 const idVec3 *getPoint(int index) {
1052 return cameraPosition->getPoint(index);
1054 return getActiveTarget()->getPoint(index);
1060 cameraPosition->stopEdit();
1062 getActiveTarget()->stopEdit();
1066 void startEdit(bool camera) {
1067 cameraEdit = camera;
1069 cameraPosition->startEdit();
1070 for (int i = 0; i < targetPositions.Num(); i++) {
1071 targetPositions[i]->stopEdit();
1074 getActiveTarget()->startEdit();
1075 cameraPosition->stopEdit();
1080 bool waitEvent(int index);
1082 const char *getName() {
1083 return name.c_str();
1086 void setName(const char *p) {
1090 idCameraPosition *getPositionObj() {
1091 if (cameraPosition == NULL) {
1092 cameraPosition = new idFixedPosition();
1094 return cameraPosition;
1099 int currentCameraPosition;
1100 idVec3 lastDirection;
1102 idCameraPosition *cameraPosition;
1103 idList<idCameraPosition*> targetPositions;
1104 idList<idCameraEvent*> events;
1115 extern bool g_splineMode;
1117 extern idCameraDef *g_splineList;