1 // timeline.cpp 2 // 3 // Object timelines. 4 // 5 // Copyright (C) 2008, the Celestia Development Team 6 // Initial version by Chris Laurel, claurel@gmail.com 7 // 8 // This program is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU General Public License 10 // as published by the Free Software Foundation; either version 2 11 // of the License, or (at your option) any later version. 12 13 #include "celengine/timeline.h" 14 #include "celengine/timelinephase.h" 15 #include "celengine/frametree.h" 16 #include "celengine/frame.h" 17 18 using namespace std; 19 20 21 /*! A Timeline is a list of TimelinePhases that covers a continuous 22 * interval of time. 23 */ 24 Timeline()25Timeline::Timeline() 26 { 27 } 28 29 ~Timeline()30Timeline::~Timeline() 31 { 32 for (vector<TimelinePhase*>::iterator iter = phases.begin(); iter != phases.end(); iter++) 33 { 34 // Remove the phase from whatever phase tree contains it. 35 TimelinePhase* phase = *iter; 36 phase->getFrameTree()->removeChild(phase); 37 38 phase->release(); 39 } 40 } 41 42 43 bool appendPhase(TimelinePhase * phase)44Timeline::appendPhase(TimelinePhase* phase) 45 { 46 // Validate start and end times. If there are existing phases in the timeline, 47 // startTime must be equal to endTime of the previous phases so that there are 48 // no gaps and no overlaps. 49 if (!phases.empty()) 50 { 51 if (phase->startTime() != phases.back()->endTime()) 52 return false; 53 } 54 55 phase->addRef(); 56 phases.push_back(phase); 57 58 return true; 59 } 60 61 62 const TimelinePhase* findPhase(double t) const63Timeline::findPhase(double t) const 64 { 65 // Find the phase containing time t. The overwhelming common case is 66 // nPhases = 1, so we special case that. Otherwise, we do a simple linear search, 67 // as the number of phases in a timeline should always be quite small. 68 if (phases.size() == 1) 69 { 70 return phases[0]; 71 } 72 else 73 { 74 for (vector<TimelinePhase*>::const_iterator iter = phases.begin(); iter != phases.end(); iter++) 75 { 76 if (t < (*iter)->endTime()) 77 return *iter; 78 } 79 80 // Time is greater than the end time of the final phase. Just return the final phase. 81 return phases.back(); 82 } 83 } 84 85 86 /*! Get the phase at the specified index. 87 */ 88 const TimelinePhase* getPhase(unsigned int n) const89Timeline::getPhase(unsigned int n) const 90 { 91 return phases.at(n); 92 } 93 94 95 /*! Get the number of phases in this timeline. 96 */ 97 unsigned int phaseCount() const98Timeline::phaseCount() const 99 { 100 return phases.size(); 101 } 102 103 104 double startTime() const105Timeline::startTime() const 106 { 107 return phases.front()->startTime(); 108 } 109 110 111 double endTime() const112Timeline::endTime() const 113 { 114 return phases.back()->endTime(); 115 } 116 117 118 /*! Check whether the timeline covers the specified time t. True if 119 * startTime <= t <= endTime. Note that this is deliberately different 120 * than the TimelinePhase::includes function, which is only true if 121 * t is strictly less than the end time. 122 */ 123 bool includes(double t) const124Timeline::includes(double t) const 125 { 126 return phases.front()->startTime() <= t && t <= phases.back()->endTime(); 127 } 128 129 130 void markChanged()131Timeline::markChanged() 132 { 133 if (phases.size() == 1) 134 { 135 phases[0]->getFrameTree()->markChanged(); 136 } 137 else 138 { 139 for (vector<TimelinePhase*>::iterator iter = phases.begin(); iter != phases.end(); iter++) 140 (*iter)->getFrameTree()->markChanged(); 141 } 142 } 143